codegen_test.cc revision a0bb2bd5b6a049ad806c223f00672d1f0210db67
1d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray/*
2d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
4d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * you may not use this file except in compliance with the License.
6d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * You may obtain a copy of the License at
7d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
8d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
10d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * See the License for the specific language governing permissions and
14d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * limitations under the License.
15d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray */
16d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
17360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include <functional>
18360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
19d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set.h"
203416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle#include "arch/arm/instruction_set_features_arm.h"
21927307433af0a9322e8ba77eda37168512a73683Alexandre Rames#include "base/macros.h"
22d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "builder.h"
238a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_arm.h"
245319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "code_generator_arm64.h"
258a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_x86.h"
268a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_x86_64.h"
27d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "common_compiler_test.h"
283ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#include "dex_file.h"
29d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "dex_instruction.h"
30cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h"
31d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h"
323ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#include "optimizing_unit_test.h"
33360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "prepare_for_register_allocation.h"
34360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "register_allocator.h"
35360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "ssa_liveness_analysis.h"
3655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#include "utils.h"
37d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
38d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "gtest/gtest.h"
39a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray
40d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art {
41d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
42a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// Provide our own codegen, that ensures the C calling conventions
43a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// are preserved. Currently, ART and C do not match as R4 is caller-save
44a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// in ART, and callee-save in C. Alternatively, we could use or write
45a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// the stub that saves and restores all registers, but it is easier
46a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// to just overwrite the code generator.
47a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffrayclass TestCodeGeneratorARM : public arm::CodeGeneratorARM {
48a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray public:
49a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  TestCodeGeneratorARM(HGraph* graph,
50a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray                       const ArmInstructionSetFeatures& isa_features,
51a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray                       const CompilerOptions& compiler_options)
52a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray      : arm::CodeGeneratorARM(graph, isa_features, compiler_options) {
53a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    AddAllocatedRegister(Location::RegisterLocation(6));
54a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    AddAllocatedRegister(Location::RegisterLocation(7));
55a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  }
56a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray
57a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  void SetupBlockedRegisters(bool is_baseline) const OVERRIDE {
58a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    arm::CodeGeneratorARM::SetupBlockedRegisters(is_baseline);
59a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    blocked_core_registers_[4] = true;
60a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    blocked_core_registers_[6] = false;
61a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    blocked_core_registers_[7] = false;
62a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    // Makes pari R6-R7 available.
63a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    blocked_register_pairs_[6 >> 1] = false;
64a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  }
65a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray};
66a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray
67787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass InternalCodeAllocator : public CodeAllocator {
68d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
69d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  InternalCodeAllocator() : size_(0) { }
70d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
71d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) {
72787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray    size_ = size;
73d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    memory_.reset(new uint8_t[size]);
74d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    return memory_.get();
75d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  }
76d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
77787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  size_t GetSize() const { return size_; }
78787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint8_t* GetMemory() const { return memory_.get(); }
79d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
80d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
81787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  size_t size_;
82700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<uint8_t[]> memory_;
83d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
84787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
85d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
86d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
8755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
888d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffraystatic void Run(const InternalCodeAllocator& allocator,
898d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray                const CodeGenerator& codegen,
908d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray                bool has_result,
9155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                Expected expected) {
9255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  typedef Expected (*fptr)();
939cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray  CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize());
9420dfc797dc631bf8d655dcf123f46f13332d3074Dave Allison  fptr f = reinterpret_cast<fptr>(allocator.GetMemory());
958d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray  if (codegen.GetInstructionSet() == kThumb2) {
968d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray    // For thumb we need the bottom bit set.
978d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray    f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1);
988d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray  }
9955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  Expected result = f();
1009cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray  if (has_result) {
101360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    ASSERT_EQ(result, expected);
1029cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray  }
1039cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray}
1049cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
10555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
10655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillainstatic void RunCodeBaseline(HGraph* graph, bool has_result, Expected expected) {
107787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  InternalCodeAllocator allocator;
1089cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
109cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  CompilerOptions compiler_options;
110cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  x86::CodeGeneratorX86 codegenX86(graph, compiler_options);
11173e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  // We avoid doing a stack overflow check that requires the runtime being setup,
11273e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  // by making sure the compiler knows the methods we are running are leaf methods.
1138a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  codegenX86.CompileBaseline(&allocator, true);
1148a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  if (kRuntimeISA == kX86) {
1158a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray    Run(allocator, codegenX86, has_result, expected);
1168a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  }
1179cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
118df64950a466c0f00cd36120d1afd389c577cae87Andreas Gampe  std::unique_ptr<const ArmInstructionSetFeatures> features(
119df64950a466c0f00cd36120d1afd389c577cae87Andreas Gampe      ArmInstructionSetFeatures::FromCppDefines());
120a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  TestCodeGeneratorARM codegenARM(graph, *features.get(), compiler_options);
1218a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  codegenARM.CompileBaseline(&allocator, true);
1228a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
1238a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray    Run(allocator, codegenARM, has_result, expected);
1248a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  }
1259cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
126cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  x86_64::CodeGeneratorX86_64 codegenX86_64(graph, compiler_options);
1278a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  codegenX86_64.CompileBaseline(&allocator, true);
1288a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  if (kRuntimeISA == kX86_64) {
1298a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray    Run(allocator, codegenX86_64, has_result, expected);
1308a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  }
1315319defdf502fc4569316473846b83180ec08035Alexandre Rames
132cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  arm64::CodeGeneratorARM64 codegenARM64(graph, compiler_options);
1335319defdf502fc4569316473846b83180ec08035Alexandre Rames  codegenARM64.CompileBaseline(&allocator, true);
1345319defdf502fc4569316473846b83180ec08035Alexandre Rames  if (kRuntimeISA == kArm64) {
1355319defdf502fc4569316473846b83180ec08035Alexandre Rames    Run(allocator, codegenARM64, has_result, expected);
1365319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
137d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
138d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
13955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
140360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void RunCodeOptimized(CodeGenerator* codegen,
141360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             HGraph* graph,
142360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             std::function<void(HGraph*)> hook_before_codegen,
143360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             bool has_result,
14455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                             Expected expected) {
145360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  SsaLivenessAnalysis liveness(*graph, codegen);
146360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  liveness.Analyze();
147360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
148360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness);
149360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  register_allocator.AllocateRegisters();
150360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  hook_before_codegen(graph);
151360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
152360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  InternalCodeAllocator allocator;
153360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  codegen->CompileOptimized(&allocator);
154360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  Run(allocator, *codegen, has_result, expected);
155360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
156360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
15755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
158360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void RunCodeOptimized(HGraph* graph,
159360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             std::function<void(HGraph*)> hook_before_codegen,
160360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             bool has_result,
16155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                             Expected expected) {
162cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  CompilerOptions compiler_options;
1633e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
164a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray    TestCodeGeneratorARM codegenARM(graph,
165a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray                                    *ArmInstructionSetFeatures::FromCppDefines(),
166a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray                                    compiler_options);
167360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    RunCodeOptimized(&codegenARM, graph, hook_before_codegen, has_result, expected);
1683e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  } else if (kRuntimeISA == kArm64) {
169cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle    arm64::CodeGeneratorARM64 codegenARM64(graph, compiler_options);
1703e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    RunCodeOptimized(&codegenARM64, graph, hook_before_codegen, has_result, expected);
1713e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  } else if (kRuntimeISA == kX86) {
172cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle    x86::CodeGeneratorX86 codegenX86(graph, compiler_options);
1733e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    RunCodeOptimized(&codegenX86, graph, hook_before_codegen, has_result, expected);
174360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  } else if (kRuntimeISA == kX86_64) {
175cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle    x86_64::CodeGeneratorX86_64 codegenX86_64(graph, compiler_options);
176360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    RunCodeOptimized(&codegenX86_64, graph, hook_before_codegen, has_result, expected);
177360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  }
178360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
179360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
180360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) {
181360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaPool pool;
182360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaAllocator arena(&pool);
183360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HGraphBuilder builder(&arena);
184360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
185360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HGraph* graph = builder.BuildGraph(*item);
186360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ASSERT_NE(graph, nullptr);
187039b6e2fd3bfadbd1ee8583002f673d6ccba5b7eCalin Juravle  // Remove suspend checks, they cannot be executed in this context.
18848dee04f4e4214b0fdd8acd0587ef6b08d3d2456Calin Juravle  RemoveSuspendChecks(graph);
189360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  RunCodeBaseline(graph, has_result, expected);
190360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
191360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
19255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillainstatic void TestCodeLong(const uint16_t* data, bool has_result, int64_t expected) {
19355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  ArenaPool pool;
19455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  ArenaAllocator arena(&pool);
19555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  HGraphBuilder builder(&arena, Primitive::kPrimLong);
19655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
19755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  HGraph* graph = builder.BuildGraph(*item);
19855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  ASSERT_NE(graph, nullptr);
19955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  // Remove suspend checks, they cannot be executed in this context.
20055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  RemoveSuspendChecks(graph);
20155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  RunCodeBaseline(graph, has_result, expected);
20255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain}
20355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
204d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas GeoffrayTEST(CodegenTest, ReturnVoid) {
2053ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID);
2063ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
207d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
208d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
209bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG1) {
2103ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
211d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
2123ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::RETURN_VOID);
213d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2143ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
215d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
216d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
217bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG2) {
2183ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
219d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
220d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
2213ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::RETURN_VOID);
222d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2233ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
224d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
225d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
226bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG3) {
2273ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
228d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x200,
229d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
2303ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO | 0xFF00);
231d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2323ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data1);
233d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2343ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
235d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO_16, 3,
236d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
2373ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO_16, 0xFFFF);
238d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2393ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data2);
240d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2413ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
242d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO_32, 4, 0,
243d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
2443ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO_32, 0xFFFF, 0xFFFF);
245d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2463ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data3);
247d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
248d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
249bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG4) {
2503ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
251d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
252d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
2533ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO | 0xFE00);
254d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2553ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
256d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
257d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
258bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG5) {
259bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
260bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
261bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ, 3,
262bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::GOTO | 0x100,
263bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN_VOID);
264bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
265bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data);
266bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
267bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
268bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, IntConstant) {
269bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
270bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
271bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN_VOID);
272bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
273bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data);
274bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
275bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
276bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return1) {
277bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
278bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
279bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0);
280bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
281bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 0);
282bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
283bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
284bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return2) {
285bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
286bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
287bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 1 << 8,
288bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
289bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
290bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 0);
291bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
292bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
293bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return3) {
294bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
295bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
296bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
297bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
298bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
299bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 1);
300bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
301bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
302bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, ReturnIf1) {
303bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
304bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
305bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
306bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ, 3,
307bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0 << 8,
308bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
309bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
310bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 1);
311bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
312bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
313bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, ReturnIf2) {
314bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
315bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
316bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
317bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ | 0 << 4 | 1 << 8, 3,
318bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0 << 8,
319bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
320bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
321bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 0);
322bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
323bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
3241cc5f251df558b0e22cea5000626365eb644c727Roland Levillain// Exercise bit-wise (one's complement) not-int instruction.
3251cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
3261cc5f251df558b0e22cea5000626365eb644c727Roland LevillainTEST(CodegenTest, TEST_NAME) {                          \
3271cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  const int32_t input = INPUT;                          \
32855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t input_lo = Low16Bits(input);           \
32955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t input_hi = High16Bits(input);          \
3301cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(      \
3311cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::CONST | 0 << 8, input_lo, input_hi,  \
3321cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::NOT_INT | 1 << 8 | 0 << 12 ,         \
3331cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::RETURN | 1 << 8);                    \
3341cc5f251df558b0e22cea5000626365eb644c727Roland Levillain                                                        \
3351cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  TestCode(data, true, EXPECTED_OUTPUT);                \
3361cc5f251df558b0e22cea5000626365eb644c727Roland Levillain}
3371cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
3381cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus2, -2, 1)
3391cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus1, -1, 0)
3401cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt0, 0, -1)
3411cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt1, 1, -2)
34255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MIN, -2147483648, 2147483647)  // (2^31) - 1
34355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MINPlus1, -2147483647, 2147483646)  // (2^31) - 2
34455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAXMinus1, 2147483646, -2147483647)  // -(2^31) - 1
34555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAX, 2147483647, -2147483648)  // -(2^31)
3461cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
3471cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#undef NOT_INT_TEST
3481cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
34955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Exercise bit-wise (one's complement) not-long instruction.
35055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define NOT_LONG_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT)                 \
35155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainTEST(CodegenTest, TEST_NAME) {                                           \
35255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const int64_t input = INPUT;                                           \
35355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));   /* LSW. */       \
35455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));                   \
35555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));                   \
35655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word3 = High16Bits(High32Bits(input)); /* MSW. */       \
35755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(                      \
35855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,      \
35955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::NOT_LONG | 2 << 8 | 0 << 12,                          \
36055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::RETURN_WIDE | 2 << 8);                                \
36155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                                                                         \
36255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  TestCodeLong(data, true, EXPECTED_OUTPUT);                             \
36355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain}
36455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
36555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus2, INT64_C(-2), INT64_C(1))
36655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus1, INT64_C(-1), INT64_C(0))
36755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong0, INT64_C(0), INT64_C(-1))
36855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong1, INT64_C(1), INT64_C(-2))
36955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
37055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MIN,
37155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483648),
37255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483647))  // (2^31) - 1
37355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MINPlus1,
37455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483647),
37555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483646))  // (2^31) - 2
37655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAXMinus1,
37755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483646),
37855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483647))  // -(2^31) - 1
37955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAX,
38055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483647),
38155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483648))  // -(2^31)
38255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
38355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Note that the C++ compiler won't accept
38455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// INT64_C(-9223372036854775808) (that is, INT64_MIN) as a valid
38555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// int64_t literal, so we use INT64_C(-9223372036854775807)-1 instead.
38655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MIN,
38755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807)-1,
38855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775807));  // (2^63) - 1
38955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MINPlus1,
39055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807),
39155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775806));  // (2^63) - 2
39255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAXMinus1,
39355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775806),
39455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807));  // -(2^63) - 1
39555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAX,
39655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775807),
39755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807)-1);  // -(2^63)
39855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
39955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#undef NOT_LONG_TEST
40055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
401946e143941d456a4ec666f7f54719c65c5aa3f5dRoland LevillainTEST(CodegenTest, IntToLongOfLongToInt) {
402946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const int64_t input = INT64_C(4294967296);             // 2^32
403946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));    // LSW.
404946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));
405946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));
406946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word3 = High16Bits(High32Bits(input));  // MSW.
407946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t data[] = FIVE_REGISTERS_CODE_ITEM(
408946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
409946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::CONST_WIDE | 2 << 8, 1, 0, 0, 0,
410946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::ADD_LONG | 0, 0 << 8 | 2,             // v0 <- 2^32 + 1
411946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::LONG_TO_INT | 4 << 8 | 0 << 12,
412946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::INT_TO_LONG | 2 << 8 | 4 << 12,
413946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::RETURN_WIDE | 2 << 8);
414946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain
415946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  TestCodeLong(data, true, 1);
416946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain}
417946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain
418d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd1) {
419d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
420d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
421d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
422d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT, 1 << 8 | 0,
423d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
424d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
425d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
426d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
427d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
428d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd2) {
429d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
430d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
431d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
432d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_2ADDR | 1 << 12,
433d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
434d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
435d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
436d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
437d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
438d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd3) {
439d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
440d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0 << 8,
441d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_LIT8, 3 << 8 | 0,
442d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
443d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
444d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
445d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
446d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
447d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd4) {
448d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
449d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0 << 8,
450d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_LIT16, 3,
451d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
452d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
453d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
454d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
455d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
456360231a056e796c36ffe62348507e904dc9efb9bNicolas GeoffrayTEST(CodegenTest, NonMaterializedCondition) {
457360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaPool pool;
458360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaAllocator allocator(&pool);
459360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
460360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HGraph* graph = new (&allocator) HGraph(&allocator);
461360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
462360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(entry);
463360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->SetEntryBlock(entry);
464360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddInstruction(new (&allocator) HGoto());
465360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
466360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* first_block = new (&allocator) HBasicBlock(graph);
467360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(first_block);
468360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddSuccessor(first_block);
469360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HIntConstant* constant0 = new (&allocator) HIntConstant(0);
470360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddInstruction(constant0);
471360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HIntConstant* constant1 = new (&allocator) HIntConstant(1);
472360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddInstruction(constant1);
473360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HEqual* equal = new (&allocator) HEqual(constant0, constant0);
474360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddInstruction(equal);
475360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddInstruction(new (&allocator) HIf(equal));
476360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
477360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* then = new (&allocator) HBasicBlock(graph);
478360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
479360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
480360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
481360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(then);
482360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(else_);
483360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(exit);
484360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddSuccessor(then);
485360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddSuccessor(else_);
486360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  then->AddSuccessor(exit);
487360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  else_->AddSuccessor(exit);
488360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
489360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  exit->AddInstruction(new (&allocator) HExit());
490360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  then->AddInstruction(new (&allocator) HReturn(constant0));
491360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  else_->AddInstruction(new (&allocator) HReturn(constant1));
492360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
493360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ASSERT_TRUE(equal->NeedsMaterialization());
494360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->BuildDominatorTree();
495360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  PrepareForRegisterAllocation(graph).Run();
496360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ASSERT_FALSE(equal->NeedsMaterialization());
497360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
498277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe  auto hook_before_codegen = [](HGraph* graph_in) {
499277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
500277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
501360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    block->InsertInstructionBefore(move, block->GetLastInstruction());
502360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  };
503360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
504360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  RunCodeOptimized(graph, hook_before_codegen, true, 0);
505360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
506360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
50734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle#define MUL_TEST(TYPE, TEST_NAME)                     \
50834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TEST(CodegenTest, Return ## TEST_NAME) {            \
50934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(  \
51034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 3 << 12 | 0,             \
51134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 4 << 12 | 1 << 8,        \
51234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::MUL_ ## TYPE, 1 << 8 | 0,          \
51334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::RETURN);                           \
51434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle                                                      \
51534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    TestCode(data, true, 12);                         \
51634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  }                                                   \
51734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle                                                      \
51834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TEST(CodegenTest, Return ## TEST_NAME ## 2addr) {   \
51934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(  \
52034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 3 << 12 | 0,             \
52134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 4 << 12 | 1 << 8,        \
52234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::MUL_ ## TYPE ## _2ADDR | 1 << 12,  \
52334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::RETURN);                           \
52434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle                                                      \
52534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    TestCode(data, true, 12);                         \
52634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  }
52734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
52834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleMUL_TEST(INT, MulInt);
52934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleMUL_TEST(LONG, MulLong);
53034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
53134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleTEST(CodegenTest, ReturnMulIntLit8) {
53234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
53334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
53434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::MUL_INT_LIT8, 3 << 8 | 0,
53534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::RETURN);
53634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
53734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TestCode(data, true, 12);
53834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle}
53934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
54034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleTEST(CodegenTest, ReturnMulIntLit16) {
54134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
54234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
54334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::MUL_INT_LIT16, 3,
54434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::RETURN);
54534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
54634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TestCode(data, true, 12);
54734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle}
54834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
549927307433af0a9322e8ba77eda37168512a73683Alexandre RamesTEST(CodegenTest, MaterializedCondition1) {
550927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // Check that condition are materialized correctly. A materialized condition
551927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // should yield `1` if it evaluated to true, and `0` otherwise.
552927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // We force the materialization of comparisons for different combinations of
553927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // inputs and check the results.
554927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
555927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int lhs[] = {1, 2, -1, 2, 0xabc};
556927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int rhs[] = {2, 1, 2, -1, 0xabc};
557927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
558927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  for (size_t i = 0; i < arraysize(lhs); i++) {
559927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaPool pool;
560927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaAllocator allocator(&pool);
561927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HGraph* graph = new (&allocator) HGraph(&allocator);
562927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
563927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
564927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(entry_block);
565927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetEntryBlock(entry_block);
566927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddInstruction(new (&allocator) HGoto());
567927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* code_block = new (&allocator) HBasicBlock(graph);
568927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(code_block);
569927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
570927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(exit_block);
571927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    exit_block->AddInstruction(new (&allocator) HExit());
572927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
573927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddSuccessor(code_block);
574927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddSuccessor(exit_block);
575927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetExitBlock(exit_block);
576927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
577927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_lhs(lhs[i]);
578927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&cst_lhs);
579927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_rhs(rhs[i]);
580927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&cst_rhs);
581927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HLessThan cmp_lt(&cst_lhs, &cst_rhs);
582927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&cmp_lt);
583927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HReturn ret(&cmp_lt);
584927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&ret);
585927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
586277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    auto hook_before_codegen = [](HGraph* graph_in) {
587277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
588277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
589927307433af0a9322e8ba77eda37168512a73683Alexandre Rames      block->InsertInstructionBefore(move, block->GetLastInstruction());
590927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    };
591927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
592927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    RunCodeOptimized(graph, hook_before_codegen, true, lhs[i] < rhs[i]);
593927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  }
594927307433af0a9322e8ba77eda37168512a73683Alexandre Rames}
595927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
596927307433af0a9322e8ba77eda37168512a73683Alexandre RamesTEST(CodegenTest, MaterializedCondition2) {
597927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // Check that HIf correctly interprets a materialized condition.
598927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // We force the materialization of comparisons for different combinations of
599927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // inputs. An HIf takes the materialized combination as input and returns a
600927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // value that we verify.
601927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
602927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int lhs[] = {1, 2, -1, 2, 0xabc};
603927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int rhs[] = {2, 1, 2, -1, 0xabc};
604927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
605927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
606927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  for (size_t i = 0; i < arraysize(lhs); i++) {
607927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaPool pool;
608927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaAllocator allocator(&pool);
609927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HGraph* graph = new (&allocator) HGraph(&allocator);
610927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
611927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
612927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(entry_block);
613927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetEntryBlock(entry_block);
614927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddInstruction(new (&allocator) HGoto());
615927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
616927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* if_block = new (&allocator) HBasicBlock(graph);
617927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(if_block);
618927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* if_true_block = new (&allocator) HBasicBlock(graph);
619927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(if_true_block);
620927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* if_false_block = new (&allocator) HBasicBlock(graph);
621927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(if_false_block);
622927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
623927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(exit_block);
624927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    exit_block->AddInstruction(new (&allocator) HExit());
625927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
626927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetEntryBlock(entry_block);
627927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddSuccessor(if_block);
628927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddSuccessor(if_true_block);
629927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddSuccessor(if_false_block);
630927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_true_block->AddSuccessor(exit_block);
631927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_false_block->AddSuccessor(exit_block);
632927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetExitBlock(exit_block);
633927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
634927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_lhs(lhs[i]);
635927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&cst_lhs);
636927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_rhs(rhs[i]);
637927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&cst_rhs);
638927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HLessThan cmp_lt(&cst_lhs, &cst_rhs);
639927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&cmp_lt);
640927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    // We insert a temporary to separate the HIf from the HLessThan and force
641927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    // the materialization of the condition.
642927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HTemporary force_materialization(0);
643927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&force_materialization);
644927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIf if_lt(&cmp_lt);
645927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&if_lt);
646927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
647927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_lt(1);
648927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_true_block->AddInstruction(&cst_lt);
649927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HReturn ret_lt(&cst_lt);
650927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_true_block->AddInstruction(&ret_lt);
651927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_ge(0);
652927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_false_block->AddInstruction(&cst_ge);
653927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HReturn ret_ge(&cst_ge);
654927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_false_block->AddInstruction(&ret_ge);
655927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
656277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    auto hook_before_codegen = [](HGraph* graph_in) {
657277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
658277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
659927307433af0a9322e8ba77eda37168512a73683Alexandre Rames      block->InsertInstructionBefore(move, block->GetLastInstruction());
660927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    };
661927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
662927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    RunCodeOptimized(graph, hook_before_codegen, true, lhs[i] < rhs[i]);
663927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  }
664927307433af0a9322e8ba77eda37168512a73683Alexandre Rames}
66534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
666d0d4852847432368b090c184d6639e573538dccfCalin JuravleTEST(CodegenTest, ReturnDivIntLit8) {
667d0d4852847432368b090c184d6639e573538dccfCalin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
668d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
669d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::DIV_INT_LIT8, 3 << 8 | 0,
670d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::RETURN);
671d0d4852847432368b090c184d6639e573538dccfCalin Juravle
672d0d4852847432368b090c184d6639e573538dccfCalin Juravle  TestCode(data, true, 1);
673d0d4852847432368b090c184d6639e573538dccfCalin Juravle}
674d0d4852847432368b090c184d6639e573538dccfCalin Juravle
675865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin JuravleTEST(CodegenTest, ReturnDivInt2Addr) {
676865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
677865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0,
678865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::CONST_4 | 2 << 12 | 1 << 8,
679865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::DIV_INT_2ADDR | 1 << 12,
680865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::RETURN);
681865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle
682865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle  TestCode(data, true, 2);
683865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle}
684865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle
685d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
686