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 */
354833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdilclass ConstantFoldingTest : public CommonCompilerTest {
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,
45ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampe                const 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,
57ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampe                            const std::function<void(HGraph*)>& check_after_cf) {
5896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    ASSERT_NE(graph_, nullptr);
5996709f17347cb7a6aae15816244d2200ca95a649Aart Bik
6096709f17347cb7a6aae15816244d2200ca95a649Aart Bik    StringPrettyPrinter printer_before(graph_);
6196709f17347cb7a6aae15816244d2200ca95a649Aart Bik    printer_before.VisitInsertionOrder();
6296709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::string actual_before = printer_before.str();
6396709f17347cb7a6aae15816244d2200ca95a649Aart Bik    EXPECT_EQ(expected_before, actual_before);
6496709f17347cb7a6aae15816244d2200ca95a649Aart Bik
6596709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
6696709f17347cb7a6aae15816244d2200ca95a649Aart Bik        X86InstructionSetFeatures::FromCppDefines());
6796709f17347cb7a6aae15816244d2200ca95a649Aart Bik    x86::CodeGeneratorX86 codegenX86(graph_, *features_x86.get(), CompilerOptions());
68ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampe    HConstantFolding(graph_, "constant_folding").Run();
69badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    GraphChecker graph_checker_cf(graph_);
70badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    graph_checker_cf.Run();
71badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    ASSERT_TRUE(graph_checker_cf.IsValid());
7296709f17347cb7a6aae15816244d2200ca95a649Aart Bik
7396709f17347cb7a6aae15816244d2200ca95a649Aart Bik    StringPrettyPrinter printer_after_cf(graph_);
7496709f17347cb7a6aae15816244d2200ca95a649Aart Bik    printer_after_cf.VisitInsertionOrder();
7596709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::string actual_after_cf = printer_after_cf.str();
7696709f17347cb7a6aae15816244d2200ca95a649Aart Bik    EXPECT_EQ(expected_after_cf, actual_after_cf);
7796709f17347cb7a6aae15816244d2200ca95a649Aart Bik
7896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    check_after_cf(graph_);
7996709f17347cb7a6aae15816244d2200ca95a649Aart Bik
80ca620d7bc03b23a0bcf0ef58df58603ee000dca0Andreas Gampe    HDeadCodeElimination(graph_, nullptr /* stats */, "dead_code_elimination").Run();
81badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    GraphChecker graph_checker_dce(graph_);
82badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    graph_checker_dce.Run();
83badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    ASSERT_TRUE(graph_checker_dce.IsValid());
8496709f17347cb7a6aae15816244d2200ca95a649Aart Bik
8596709f17347cb7a6aae15816244d2200ca95a649Aart Bik    StringPrettyPrinter printer_after_dce(graph_);
8696709f17347cb7a6aae15816244d2200ca95a649Aart Bik    printer_after_dce.VisitInsertionOrder();
8796709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::string actual_after_dce = printer_after_dce.str();
8896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    EXPECT_EQ(expected_after_dce, actual_after_dce);
8996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  }
9096709f17347cb7a6aae15816244d2200ca95a649Aart Bik
9196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  ArenaPool pool_;
9296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  ArenaAllocator allocator_;
9396709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HGraph* graph_;
9496709f17347cb7a6aae15816244d2200ca95a649Aart Bik};
95556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
96556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
979240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain * Tiny three-register program exercising int constant folding on negation.
989240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *
999240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              16-bit
1009240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              offset
1019240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              ------
1029240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
103c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     v1 <- -v0                1.      neg-int v1, v0
1049240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *     return v1                2.      return v1
1059240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain */
10696709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingNegation) {
1079240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
1089240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
1099240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::NEG_INT | 1 << 8 | 0 << 12,
1109240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::RETURN | 1 << 8);
1119240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1129240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_before =
1139240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 0, succ: 1\n"
114dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: IntConstant [3]\n"
115dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
116dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
1179240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 1, pred: 0, succ: 2\n"
118dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: Neg(2) [4]\n"
119dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Return(3)\n"
1209240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 2, pred: 1\n"
121dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: Exit\n";
1229240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1239240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Expected difference after constant folding.
1249240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  diff_t expected_cf_diff = {
125dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant [3]\n", "  2: IntConstant\n"
126dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                "  6: IntConstant [4]\n" },
127dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: Neg(2) [4]\n",      removed },
128dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Return(3)\n",       "  4: Return(6)\n" }
1299240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1309240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
1319240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1329240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Check the value of the computed constant.
1339240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  auto check_after_cf = [](HGraph* graph) {
134ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
1359240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    ASSERT_TRUE(inst->IsIntConstant());
1369240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), -1);
1379240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1389240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1399240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Expected difference after dead code elimination.
1409240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  diff_t expected_dce_diff = {
141dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant\n", removed },
1429240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1439240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
1449240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1459240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  TestCode(data,
1469240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_before,
1479240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_after_cf,
1489240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_after_dce,
1499240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           check_after_cf);
1509240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain}
1519240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1529240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain/**
153c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain * Tiny three-register program exercising long constant folding on negation.
154c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *
155c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *                              16-bit
156c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *                              offset
157c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *                              ------
158c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     (v0, v1) <- 4294967296   0.      const-wide v0 #+4294967296
159c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     (v2, v3) <- -(v0, v1)    1.      neg-long v2, v0
160c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     return (v2, v3)          2.      return-wide v2
161c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain */
16296709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, LongConstantFoldingNegation) {
163c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const int64_t input = INT64_C(4294967296);             // 2^32
164c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));    // LSW.
165c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));
166c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));
167c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word3 = High16Bits(High32Bits(input));  // MSW.
168c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(
169c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
170c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    Instruction::NEG_LONG | 2 << 8 | 0 << 12,
171c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    Instruction::RETURN_WIDE | 2 << 8);
172c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
173c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  std::string expected_before =
174c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "BasicBlock 0, succ: 1\n"
175dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: LongConstant [3]\n"
176dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
177dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
178c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "BasicBlock 1, pred: 0, succ: 2\n"
179dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: Neg(2) [4]\n"
180dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Return(3)\n"
181c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "BasicBlock 2, pred: 1\n"
182dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: Exit\n";
183c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
184c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  // Expected difference after constant folding.
185c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  diff_t expected_cf_diff = {
186dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: LongConstant [3]\n", "  2: LongConstant\n"
187dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                 "  6: LongConstant [4]\n" },
188dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: Neg(2) [4]\n",       removed },
189dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Return(3)\n",        "  4: Return(6)\n" }
190c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  };
191c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
192c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
193c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  // Check the value of the computed constant.
194c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  auto check_after_cf = [](HGraph* graph) {
195ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
196c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    ASSERT_TRUE(inst->IsLongConstant());
197c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), INT64_C(-4294967296));
198c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  };
199c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
200c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  // Expected difference after dead code elimination.
201c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  diff_t expected_dce_diff = {
202dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: LongConstant\n", removed },
203c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  };
204c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
205c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
206c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  TestCode(data,
207c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           expected_before,
208c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           expected_after_cf,
209c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           expected_after_dce,
210c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           check_after_cf,
211c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           Primitive::kPrimLong);
212c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain}
213c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
214c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain/**
215556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on addition.
216556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
217556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
218556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
219556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
220556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
221556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
222556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            2.      add-int v2, v0, v1
223556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
224556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
22596709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition1) {
226556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
227556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
228556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
229556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
230556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
231556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
232556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
23386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
234dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: IntConstant [4]\n"
235dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: IntConstant [4]\n"
236dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
237dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
23886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 2\n"
239dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Add(2, 3) [5]\n"
240dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: Return(4)\n"
24186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 2, pred: 1\n"
242dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  6: Exit\n";
243556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
24475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
24575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
246dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant [4]\n", "  2: IntConstant\n" },
247dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant [4]\n", "  3: IntConstant\n"
248dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                "  7: IntConstant [5]\n" },
249dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Add(2, 3) [5]\n",   removed },
250dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  5: Return(4)\n",       "  5: Return(7)\n" }
251556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
25275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
253556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
25493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
25575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
256ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
25793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
25893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3);
25993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
26093445689c714e53cabf347da4321ecf3023e926cRoland Levillain
261556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
262556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
263dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant\n", removed },
264dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant\n", removed }
265556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
26675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
267556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
26893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
26993445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
27075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
27193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
27275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
273556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
274556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
275556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
276556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Small three-register program exercising int constant folding on addition.
277556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
278556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
279556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
280556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
281556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
282556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
283556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v0 + v1            2.      add-int/2addr v0, v1
2848d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v1 <- 4                  3.      const/4 v1, #+4
2858d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v2 <- 5                  4.      const/4 v2, #+5
286556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- v1 + v2            5.      add-int/2addr v1, v2
287556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            6.      add-int v2, v0, v1
288556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                8.      return v2
289556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
29096709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition2) {
291556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
292556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
293556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
294556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 0 << 8 | 1 << 12,
2958d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 1 << 8 | 4 << 12,
2968d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 2 << 8 | 5 << 12,
297556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 1 << 8 | 2 << 12,
298556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
299556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
300556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
301556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
30286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
303dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: IntConstant [4]\n"
304dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: IntConstant [4]\n"
305dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: IntConstant [7]\n"
306dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  6: IntConstant [7]\n"
307dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
308dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
30986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 2\n"
310dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Add(2, 3) [8]\n"
311dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  7: Add(5, 6) [8]\n"
312dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  8: Add(4, 7) [9]\n"
313dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  9: Return(8)\n"
31486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 2, pred: 1\n"
315dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  10: Exit\n";
316556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
31775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
31875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
319dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant [4]\n",  "  2: IntConstant\n" },
320dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant [4]\n",  "  3: IntConstant\n" },
321dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  5: IntConstant [7]\n",  "  5: IntConstant\n" },
322dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  6: IntConstant [7]\n",  "  6: IntConstant\n"
323dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                 "  11: IntConstant\n"
324dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                 "  12: IntConstant\n"
325dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                 "  13: IntConstant [9]\n" },
326dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Add(2, 3) [8]\n",    removed },
327dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  7: Add(5, 6) [8]\n",    removed },
328dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  8: Add(4, 7) [9]\n",    removed  },
329dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  9: Return(8)\n",        "  9: Return(13)\n" }
330556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
33175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
332556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
33393445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
33475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
335ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst1 = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
33693445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
3378d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 12);
3388d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst2 = inst1->GetPrevious();
33993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
3408d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 9);
3418d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst3 = inst2->GetPrevious();
34293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
3438d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 3);
34493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
34593445689c714e53cabf347da4321ecf3023e926cRoland Levillain
346556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
347556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
348dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant\n",  removed },
349dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant\n",  removed },
350556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n",  removed },
351dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  6: IntConstant\n",  removed },
352dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  11: IntConstant\n", removed },
353dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  12: IntConstant\n", removed }
354556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
35575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
356556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
35793445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
35893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
35975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
36093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
36175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
362556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
363556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
364556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
365556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on subtraction.
366556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
367556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
368556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
369556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
370556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 3                  0.      const/4 v0, #+3
371556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
372556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 - v1            2.      sub-int v2, v0, v1
373556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
374556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
37596709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingOnSubtraction) {
376556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
377556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 3 << 12,
378556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
379556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_INT | 2 << 8, 0 | 1 << 8,
380556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
381556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
382556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
38386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
384dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: IntConstant [4]\n"
385dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: IntConstant [4]\n"
386dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
387dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
38886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 2\n"
389dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Sub(2, 3) [5]\n"
390dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: Return(4)\n"
39186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 2, pred: 1\n"
392dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  6: Exit\n";
393556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
39475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
39575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
396dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant [4]\n",  "  2: IntConstant\n" },
397dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant [4]\n",  "  3: IntConstant\n"
398dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                 "  7: IntConstant [5]\n" },
399dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Sub(2, 3) [5]\n",    removed },
400dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  5: Return(4)\n",        "  5: Return(7)\n" }
401556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
40275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
403556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
40493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
40575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
406ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
40793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
40893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
40993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
41093445689c714e53cabf347da4321ecf3023e926cRoland Levillain
411556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
412556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
413dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant\n", removed },
414dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant\n", removed }
415556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
41675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
417556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
41893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
41993445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
42075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
42193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
42275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
423556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
424556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
425556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
426556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
427556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on addition.
428556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
429556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
430556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
431556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
432556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 1            0.      const-wide/16 v0, #+1
433556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
434556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
435556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) + (v1, v2)    4.      add-long v4, v0, v2
436556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
437556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
43896709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, LongConstantFoldingOnAddition) {
439556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
440556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 1,
441556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
442556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_LONG | 4 << 8, 0 | 2 << 8,
443556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
444556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
445556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
44686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
447dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: LongConstant [4]\n"
448dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: LongConstant [4]\n"
449dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
450dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
45186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 2\n"
452dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Add(2, 3) [5]\n"
453dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: Return(4)\n"
45486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 2, pred: 1\n"
455dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  6: Exit\n";
456556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
45775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
45875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
459dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: LongConstant [4]\n",  "  2: LongConstant\n" },
460dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: LongConstant [4]\n",  "  3: LongConstant\n"
461dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                  "  7: LongConstant [5]\n" },
462dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Add(2, 3) [5]\n",     removed },
463dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  5: Return(4)\n",         "  5: Return(7)\n" }
464556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
46575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
466556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
46793445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
46875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
469ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
47093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
47193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3);
47293445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
47393445689c714e53cabf347da4321ecf3023e926cRoland Levillain
474556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
475556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
476dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: LongConstant\n", removed },
477dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: LongConstant\n", removed }
478556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
47975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
480556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
48193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
48293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
48375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
48493445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
48575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf,
48693445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
487556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
488556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
489556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
490556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
491556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on subtraction.
492556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
493556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
494556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
495556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
496556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 3            0.      const-wide/16 v0, #+3
497556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
498556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
499556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) - (v1, v2)    4.      sub-long v4, v0, v2
500556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
501556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
50296709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, LongConstantFoldingOnSubtraction) {
503556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
504556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 3,
505556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
506556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_LONG | 4 << 8, 0 | 2 << 8,
507556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
508556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
509556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
51086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
511dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: LongConstant [4]\n"
512dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: LongConstant [4]\n"
513dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
514dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
51586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 2\n"
516dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Sub(2, 3) [5]\n"
517dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: Return(4)\n"
51886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 2, pred: 1\n"
519dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  6: Exit\n";
520556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
52175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
52275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
523dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: LongConstant [4]\n",  "  2: LongConstant\n" },
524dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: LongConstant [4]\n",  "  3: LongConstant\n"
525dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                  "  7: LongConstant [5]\n" },
526dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Sub(2, 3) [5]\n",     removed },
527dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  5: Return(4)\n",         "  5: Return(7)\n" }
528556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
52975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
530556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
53193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
53275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
533ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
53493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
53593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1);
53693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
53793445689c714e53cabf347da4321ecf3023e926cRoland Levillain
538556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
539556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
540dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: LongConstant\n", removed },
541dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: LongConstant\n", removed }
542556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
54375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
544556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
54593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
54693445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
54775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
54893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
54975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf,
55093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
551556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
552556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
553556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
554556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with jumps leading to the creation of many
555556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * blocks.
556556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
557556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * The intent of this test is to ensure that all constant expressions
558556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * are actually evaluated at compile-time, thanks to the reverse
559556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (forward) post-order traversal of the the dominator tree.
560556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
561556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
562556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
563556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
5648d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v0 <- 1                   0.     const/4 v0, #+1
5658d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v1 <- 2                   1.     const/4 v1, #+2
566556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1             2.     add-int v2, v0, v1
567556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L2                   4.     goto +4
5688d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L1: v1 <- v0 + 5              5.     add-int/lit16 v1, v0, #+5
569556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L3                   7.     goto +4
5708d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L2: v0 <- v2 + 4              8.     add-int/lit16 v0, v2, #+4
571556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L1                  10.     goto +(-5)
5728d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L3: v2 <- v1 + 8             11.     add-int/lit16 v2, v1, #+8
573556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                13.     return v2
574556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
57596709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingAndJumps) {
576556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
5778d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 0 << 8 | 1 << 12,
5788d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 1 << 8 | 2 << 12,
579556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
580556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
5818d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 1 << 8 | 0 << 12, 5,
582556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
5838d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 0 << 8 | 2 << 12, 4,
58458554b7de4b437ddef7ff550e62c8ec0b16f9264Andreas Gampe    static_cast<uint16_t>(Instruction::GOTO | 0xFFFFFFFB << 8),
5858d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 2 << 8 | 1 << 12, 8,
586556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
587556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
588556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
58986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
590dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: IntConstant [4]\n"             // v0 <- 1
591dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: IntConstant [4]\n"             // v1 <- 2
592dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  6: IntConstant [7]\n"             // const 5
593dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  9: IntConstant [10]\n"            // const 4
594dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  12: IntConstant [13]\n"           // const 8
595dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
596dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
59786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 3\n"
598dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: Add(2, 3) [7]\n"               // v2 <- v0 + v1 = 1 + 2 = 3
599dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: Goto 3\n"                      // goto L2
60086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 2, pred: 3, succ: 4\n"   // L1:
601dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  10: Add(7, 9) [13]\n"             // v1 <- v0 + 3 = 7 + 5 = 12
602dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  11: Goto 4\n"                     // goto L3
60386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 3, pred: 1, succ: 2\n"   // L2:
604dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  7: Add(4, 6) [10]\n"              // v0 <- v2 + 2 = 3 + 4 = 7
605dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  8: Goto 2\n"                      // goto L1
60686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 4, pred: 2, succ: 5\n"   // L3:
607dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  13: Add(10, 12) [14]\n"           // v2 <- v1 + 4 = 12 + 8 = 20
608dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  14: Return(13)\n"                 // return v2
60986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 5, pred: 4\n"
610dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  15: Exit\n";
611556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
61275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
61375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
614dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  2: IntConstant [4]\n",   "  2: IntConstant\n" },
615dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant [4]\n",   "  3: IntConstant\n" },
616dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  6: IntConstant [7]\n",   "  6: IntConstant\n" },
617dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  9: IntConstant [10]\n",  "  9: IntConstant\n" },
618dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  12: IntConstant [13]\n", "  12: IntConstant\n"
619dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                  "  16: IntConstant\n"
620dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                  "  17: IntConstant\n"
621dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                  "  18: IntConstant\n"
622dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil                                  "  19: IntConstant [14]\n" },
623dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: Add(2, 3) [7]\n",     removed },
624dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  10: Add(7, 9) [13]\n",   removed },
625dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  7: Add(4, 6) [10]\n",    removed },
626dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  13: Add(10, 12) [14]\n", removed },
627dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  14: Return(13)\n",       "  14: Return(19)\n"}
628556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
62975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
630556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
63193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
63275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
633ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst1 = graph->GetBlocks()[4]->GetFirstInstruction()->InputAt(0);
63493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
6358d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 20);
6368d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst2 = inst1->GetPrevious();
63793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
6388d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 12);
6398d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst3 = inst2->GetPrevious();
64093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
6418d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 7);
6428d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst4 = inst3->GetPrevious();
64393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst4->IsIntConstant());
6448d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst4->AsIntConstant()->GetValue(), 3);
64593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
64693445689c714e53cabf347da4321ecf3023e926cRoland Levillain
647556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
6481c533c17baff841e383a539fdd3c0a65135181b0David Brazdil  std::string expected_after_dce =
64986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
650dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  19: IntConstant [14]\n"
651dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  0: SuspendCheck\n"
652dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: Goto 1\n"
65386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 5\n"
654dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  14: Return(19)\n"
65586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 5, pred: 1\n"
656dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  15: Exit\n";
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/**
666556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with a constant (static) condition.
667556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
668556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
669556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
670556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
671556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 1                  0.      const/4 v1, #+1
672556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 0                  1.      const/4 v0, #+0
673556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     if v1 >= 0 goto L1       2.      if-gez v1, +3
674556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v1                 4.      move v0, v1
675556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L1: v2 <- v0 + v1            5.      add-int v2, v0, v1
676556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return-void              7.      return
677556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
67896709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, ConstantCondition) {
679556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
680556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 1 << 12,
681556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 0 << 12,
682556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::IF_GEZ | 1 << 8, 3,
683556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::MOVE | 0 << 8 | 1 << 12,
684556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
685556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_VOID);
686556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
687556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
688dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "BasicBlock 0, succ: 1\n"
689dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  3: IntConstant [9, 8, 5]\n"
690dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  4: IntConstant [8, 5]\n"
691dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: SuspendCheck\n"
692dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: Goto 1\n"
69386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 5, 2\n"
694dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  5: GreaterThanOrEqual(3, 4) [6]\n"
695dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  6: If(5)\n"
69686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 2, pred: 1, succ: 3\n"
697dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  7: Goto 3\n"
69886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 3, pred: 5, 2, succ: 4\n"
699dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  8: Phi(4, 3) [9]\n"
700dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  9: Add(8, 3)\n"
701dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  10: ReturnVoid\n"
70286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 4, pred: 3\n"
703dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  11: Exit\n"
70486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 5, pred: 1, succ: 3\n"
70586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  0: Goto 3\n";
706556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
70775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
70875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
709dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  3: IntConstant [9, 8, 5]\n",        "  3: IntConstant [6, 9, 8]\n" },
710dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  4: IntConstant [8, 5]\n",           "  4: IntConstant [8]\n" },
711dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  5: GreaterThanOrEqual(3, 4) [6]\n", removed },
712dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil    { "  6: If(5)\n",                        "  6: If(3)\n" }
713556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
71475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
715556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
71693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
71775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
718ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
71993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
72093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
72193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
72293445689c714e53cabf347da4321ecf3023e926cRoland Levillain
7231c533c17baff841e383a539fdd3c0a65135181b0David Brazdil  // Expected graph after dead code elimination.
7241c533c17baff841e383a539fdd3c0a65135181b0David Brazdil  std::string expected_after_dce =
72586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 0, succ: 1\n"
726dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  1: SuspendCheck\n"
727dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  2: Goto 1\n"
72886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 1, pred: 0, succ: 4\n"
729dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  10: ReturnVoid\n"
73086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "BasicBlock 4, pred: 1\n"
731dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil      "  11: Exit\n";
732556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
73393445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
73493445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
73575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
73693445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
73775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
738556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
739556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
74096709f17347cb7a6aae15816244d2200ca95a649Aart Bik/**
74196709f17347cb7a6aae15816244d2200ca95a649Aart Bik * Unsigned comparisons with zero. Since these instructions are not present
74296709f17347cb7a6aae15816244d2200ca95a649Aart Bik * in the bytecode, we need to set up the graph explicitly.
74396709f17347cb7a6aae15816244d2200ca95a649Aart Bik */
74496709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, UnsignedComparisonsWithZero) {
74596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_ = CreateGraph(&allocator_);
74696709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HBasicBlock* entry_block = new (&allocator_) HBasicBlock(graph_);
74796709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->AddBlock(entry_block);
74896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->SetEntryBlock(entry_block);
74996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HBasicBlock* block = new (&allocator_) HBasicBlock(graph_);
75096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->AddBlock(block);
75196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HBasicBlock* exit_block = new (&allocator_) HBasicBlock(graph_);
75296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->AddBlock(exit_block);
75396709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->SetExitBlock(exit_block);
75496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  entry_block->AddSuccessor(block);
75596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddSuccessor(exit_block);
75696709f17347cb7a6aae15816244d2200ca95a649Aart Bik
75796709f17347cb7a6aae15816244d2200ca95a649Aart Bik  // Make various unsigned comparisons with zero against a parameter.
75896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HInstruction* parameter = new (&allocator_) HParameterValue(
759a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe      graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt, true);
76096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  entry_block->AddInstruction(parameter);
76186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  entry_block->AddInstruction(new (&allocator_) HGoto());
76286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil
76396709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HInstruction* zero = graph_->GetIntConstant(0);
76486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil
76596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HInstruction* last;
76696709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAbove(zero, parameter));
767badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
76896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAbove(parameter, zero));
769badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
77096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAboveOrEqual(zero, parameter));
771badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
77296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAboveOrEqual(parameter, zero));
773badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
77496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelow(zero, parameter));
775badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
77696709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelow(parameter, zero));
777badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
77896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelowOrEqual(zero, parameter));
779badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
78096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelowOrEqual(parameter, zero));
781badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
78296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HReturn(zero));
78386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil
78496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  exit_block->AddInstruction(new (&allocator_) HExit());
78596709f17347cb7a6aae15816244d2200ca95a649Aart Bik
786badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  graph_->BuildDominatorTree();
787badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil
78896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  const std::string expected_before =
78996709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 0, succ: 1\n"
79086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  0: ParameterValue [18, 18, 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 10, 10, 9, "
79186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil                            "8, 8, 7, 6, 6, 5, 4, 4, 3]\n"
79286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  2: IntConstant [19, 17, 15, 13, 11, 9, 7, 5, 3]\n"
79386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  1: Goto 1\n"
79496709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 1, pred: 0, succ: 2\n"
79586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  3: Above(2, 0) [4]\n"
79686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  4: Select(0, 0, 3)\n"
79786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  5: Above(0, 2) [6]\n"
79886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  6: Select(0, 0, 5)\n"
79986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  7: AboveOrEqual(2, 0) [8]\n"
80086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  8: Select(0, 0, 7)\n"
80186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  9: AboveOrEqual(0, 2) [10]\n"
80286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  10: Select(0, 0, 9)\n"
80386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  11: Below(2, 0) [12]\n"
80486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  12: Select(0, 0, 11)\n"
80586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  13: Below(0, 2) [14]\n"
80686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  14: Select(0, 0, 13)\n"
80786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  15: BelowOrEqual(2, 0) [16]\n"
80886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  16: Select(0, 0, 15)\n"
80986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  17: BelowOrEqual(0, 2) [18]\n"
81086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  18: Select(0, 0, 17)\n"
81186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  19: Return(2)\n"
81296709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 2, pred: 1\n"
81396709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  20: Exit\n";
81496709f17347cb7a6aae15816244d2200ca95a649Aart Bik
81596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  const std::string expected_after_cf =
81696709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 0, succ: 1\n"
81786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  0: ParameterValue [18, 18, 17, 16, 16, 14, 14, 12, 12, 11, 10, 10, "
81886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil                            "8, 8, 7, 6, 6, 5, 4, 4]\n"
81986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  2: IntConstant [14, 4, 19, 17, 11, 7, 5]\n"
82086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  21: IntConstant [16, 10]\n"
82186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  1: Goto 1\n"
82296709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 1, pred: 0, succ: 2\n"
82386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  4: Select(0, 0, 2)\n"
82486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  5: Above(0, 2) [6]\n"
82586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  6: Select(0, 0, 5)\n"
82686ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  7: AboveOrEqual(2, 0) [8]\n"
82786ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  8: Select(0, 0, 7)\n"
82886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  10: Select(0, 0, 21)\n"
82986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  11: Below(2, 0) [12]\n"
83086ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  12: Select(0, 0, 11)\n"
83186ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  14: Select(0, 0, 2)\n"
83286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  16: Select(0, 0, 21)\n"
83386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  17: BelowOrEqual(0, 2) [18]\n"
83486ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  18: Select(0, 0, 17)\n"
83586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  19: Return(2)\n"
83696709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 2, pred: 1\n"
83796709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  20: Exit\n";
83896709f17347cb7a6aae15816244d2200ca95a649Aart Bik
839badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  const std::string expected_after_dce =
840badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      "BasicBlock 0, succ: 1\n"
841badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      "  0: ParameterValue\n"
84286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  2: IntConstant [19]\n"
84386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  1: Goto 1\n"
844badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      "BasicBlock 1, pred: 0, succ: 2\n"
84586ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil      "  19: Return(2)\n"
846badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      "BasicBlock 2, pred: 1\n"
847badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      "  20: Exit\n";
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