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"
215da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray#include "arch/arm/registers_arm.h"
22579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu#include "arch/arm64/instruction_set_features_arm64.h"
23f652cecb984c104d44a0223c3c98400ef8ed8ce2Goran Jakovljevic#include "arch/mips/instruction_set_features_mips.h"
24f652cecb984c104d44a0223c3c98400ef8ed8ce2Goran Jakovljevic#include "arch/mips/registers_mips.h"
254dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "arch/mips64/instruction_set_features_mips64.h"
264dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "arch/mips64/registers_mips64.h"
27fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell#include "arch/x86/instruction_set_features_x86.h"
285da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray#include "arch/x86/registers_x86.h"
29fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell#include "arch/x86_64/instruction_set_features_x86_64.h"
30927307433af0a9322e8ba77eda37168512a73683Alexandre Rames#include "base/macros.h"
31d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "builder.h"
328a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_arm.h"
335319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "code_generator_arm64.h"
34f652cecb984c104d44a0223c3c98400ef8ed8ce2Goran Jakovljevic#include "code_generator_mips.h"
354dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "code_generator_mips64.h"
368a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_x86.h"
378a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_x86_64.h"
38751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang#include "code_simulator_container.h"
39d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "common_compiler_test.h"
403ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#include "dex_file.h"
41d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "dex_instruction.h"
42cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h"
4358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil#include "graph_checker.h"
44d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h"
453ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#include "optimizing_unit_test.h"
46360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "prepare_for_register_allocation.h"
47360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "register_allocator.h"
48360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "ssa_liveness_analysis.h"
4955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#include "utils.h"
505da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray#include "utils/arm/managed_register_arm.h"
51f652cecb984c104d44a0223c3c98400ef8ed8ce2Goran Jakovljevic#include "utils/mips/managed_register_mips.h"
524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "utils/mips64/managed_register_mips64.h"
535da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray#include "utils/x86/managed_register_x86.h"
54d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
55d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "gtest/gtest.h"
56e6362281bb4586f45fd927e9cd1b3b14c6b037edNicolas Geoffray
57d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art {
58d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
59a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// Provide our own codegen, that ensures the C calling conventions
60a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// are preserved. Currently, ART and C do not match as R4 is caller-save
61a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// in ART, and callee-save in C. Alternatively, we could use or write
62a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// the stub that saves and restores all registers, but it is easier
63a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// to just overwrite the code generator.
64a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffrayclass TestCodeGeneratorARM : public arm::CodeGeneratorARM {
65a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray public:
66a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  TestCodeGeneratorARM(HGraph* graph,
67a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray                       const ArmInstructionSetFeatures& isa_features,
68a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray                       const CompilerOptions& compiler_options)
69a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray      : arm::CodeGeneratorARM(graph, isa_features, compiler_options) {
705da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    AddAllocatedRegister(Location::RegisterLocation(arm::R6));
715da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    AddAllocatedRegister(Location::RegisterLocation(arm::R7));
72a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  }
73a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray
7458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  void SetupBlockedRegisters() const OVERRIDE {
7558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    arm::CodeGeneratorARM::SetupBlockedRegisters();
765da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_core_registers_[arm::R4] = true;
775da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_core_registers_[arm::R6] = false;
785da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_core_registers_[arm::R7] = false;
79e6362281bb4586f45fd927e9cd1b3b14c6b037edNicolas Geoffray    // Makes pair R6-R7 available.
805da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_register_pairs_[arm::R6_R7] = false;
815da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray  }
825da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray};
835da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
845da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffrayclass TestCodeGeneratorX86 : public x86::CodeGeneratorX86 {
855da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray public:
865da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray  TestCodeGeneratorX86(HGraph* graph,
875da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray                       const X86InstructionSetFeatures& isa_features,
885da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray                       const CompilerOptions& compiler_options)
895da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray      : x86::CodeGeneratorX86(graph, isa_features, compiler_options) {
905da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    // Save edi, we need it for getting enough registers for long multiplication.
915da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    AddAllocatedRegister(Location::RegisterLocation(x86::EDI));
925da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray  }
935da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
9458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  void SetupBlockedRegisters() const OVERRIDE {
9558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    x86::CodeGeneratorX86::SetupBlockedRegisters();
965da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    // ebx is a callee-save register in C, but caller-save for ART.
975da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_core_registers_[x86::EBX] = true;
985da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_register_pairs_[x86::EAX_EBX] = true;
995da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_register_pairs_[x86::EDX_EBX] = true;
1005da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_register_pairs_[x86::ECX_EBX] = true;
1015da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_register_pairs_[x86::EBX_EDI] = true;
1025da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
1035da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    // Make edi available.
1045da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_core_registers_[x86::EDI] = false;
1055da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    blocked_register_pairs_[x86::ECX_EDI] = false;
106a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray  }
107a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray};
108a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray
109787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass InternalCodeAllocator : public CodeAllocator {
110d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
111d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  InternalCodeAllocator() : size_(0) { }
112d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
113d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) {
114787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray    size_ = size;
115d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    memory_.reset(new uint8_t[size]);
116d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    return memory_.get();
117d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  }
118d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
119787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  size_t GetSize() const { return size_; }
120787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint8_t* GetMemory() const { return memory_.get(); }
121d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
122d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
123787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  size_t size_;
124700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<uint8_t[]> memory_;
125d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
126787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
127d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
128d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
129751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangstatic bool CanExecuteOnHardware(InstructionSet target_isa) {
130751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  return (target_isa == kRuntimeISA)
131751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang      // Handle the special case of ARM, with two instructions sets (ARM32 and Thumb-2).
132751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang      || (kRuntimeISA == kArm && target_isa == kThumb2);
133751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang}
134751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
135751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangstatic bool CanExecute(InstructionSet target_isa) {
136751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  CodeSimulatorContainer simulator(target_isa);
137751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  return CanExecuteOnHardware(target_isa) || simulator.CanSimulate();
138751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang}
139751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
140751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangtemplate <typename Expected>
141751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangstatic Expected SimulatorExecute(CodeSimulator* simulator, Expected (*f)());
142751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
143751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangtemplate <>
144751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangbool SimulatorExecute<bool>(CodeSimulator* simulator, bool (*f)()) {
145751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  simulator->RunFrom(reinterpret_cast<intptr_t>(f));
146751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  return simulator->GetCReturnBool();
147751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang}
148751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
149751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangtemplate <>
150751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangint32_t SimulatorExecute<int32_t>(CodeSimulator* simulator, int32_t (*f)()) {
151751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  simulator->RunFrom(reinterpret_cast<intptr_t>(f));
152751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  return simulator->GetCReturnInt32();
153751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang}
154751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
155751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangtemplate <>
156751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangint64_t SimulatorExecute<int64_t>(CodeSimulator* simulator, int64_t (*f)()) {
157751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  simulator->RunFrom(reinterpret_cast<intptr_t>(f));
158751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  return simulator->GetCReturnInt64();
159751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang}
160751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
161751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangtemplate <typename Expected>
162751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangstatic void VerifyGeneratedCode(InstructionSet target_isa,
163751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                                Expected (*f)(),
164751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                                bool has_result,
165751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                                Expected expected) {
166751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  ASSERT_TRUE(CanExecute(target_isa)) << "Target isa is not executable.";
167751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
168751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  // Verify on simulator.
169751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  CodeSimulatorContainer simulator(target_isa);
170751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  if (simulator.CanSimulate()) {
171751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    Expected result = SimulatorExecute<Expected>(simulator.Get(), f);
172751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    if (has_result) {
173751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang      ASSERT_EQ(expected, result);
174751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    }
175751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  }
176751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
177751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  // Verify on hardware.
178751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  if (CanExecuteOnHardware(target_isa)) {
179751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    Expected result = f();
180751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    if (has_result) {
181751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang      ASSERT_EQ(expected, result);
182751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    }
183751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  }
184751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang}
185751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
18655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
1878d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffraystatic void Run(const InternalCodeAllocator& allocator,
1888d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray                const CodeGenerator& codegen,
1898d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray                bool has_result,
19055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                Expected expected) {
191751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  InstructionSet target_isa = codegen.GetInstructionSet();
192751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
19355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  typedef Expected (*fptr)();
1949cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray  CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize());
19520dfc797dc631bf8d655dcf123f46f13332d3074Dave Allison  fptr f = reinterpret_cast<fptr>(allocator.GetMemory());
196751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  if (target_isa == kThumb2) {
1978d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray    // For thumb we need the bottom bit set.
1988d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray    f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1);
1998d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray  }
200751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  VerifyGeneratedCode(target_isa, f, has_result, expected);
2019cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray}
2029cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
20355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
20458282f4510961317b8d5a364a6f740a78926716fDavid Brazdilstatic void RunCode(CodeGenerator* codegen,
20558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    HGraph* graph,
20658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    std::function<void(HGraph*)> hook_before_codegen,
20758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    bool has_result,
20858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    Expected expected) {
209badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  GraphChecker graph_checker(graph);
21058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  graph_checker.Run();
211badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  if (!graph_checker.IsValid()) {
212badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    for (auto error : graph_checker.GetErrors()) {
213badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      std::cout << error << std::endl;
214badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    }
215badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  }
21658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  ASSERT_TRUE(graph_checker.IsValid());
217d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2180d9f17de8f21a10702de1510b73e89d07b3b9bbfNicolas Geoffray  SsaLivenessAnalysis liveness(graph, codegen);
219360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
22058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  PrepareForRegisterAllocation(graph).Run();
22158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  liveness.Analyze();
22258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  RegisterAllocator(graph->GetArena(), codegen, liveness).AllocateRegisters();
223360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  hook_before_codegen(graph);
224360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
225360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  InternalCodeAllocator allocator;
22658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  codegen->Compile(&allocator);
227360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  Run(allocator, *codegen, has_result, expected);
228360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
229360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
23055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
23158282f4510961317b8d5a364a6f740a78926716fDavid Brazdilstatic void RunCode(InstructionSet target_isa,
23258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    HGraph* graph,
23358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    std::function<void(HGraph*)> hook_before_codegen,
23458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    bool has_result,
23558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil                    Expected expected) {
236cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  CompilerOptions compiler_options;
237751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  if (target_isa == kArm || target_isa == kThumb2) {
238751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    std::unique_ptr<const ArmInstructionSetFeatures> features_arm(
239751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang        ArmInstructionSetFeatures::FromCppDefines());
240751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    TestCodeGeneratorARM codegenARM(graph, *features_arm.get(), compiler_options);
24158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(&codegenARM, graph, hook_before_codegen, has_result, expected);
242751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  } else if (target_isa == kArm64) {
243751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64(
244751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang        Arm64InstructionSetFeatures::FromCppDefines());
245751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    arm64::CodeGeneratorARM64 codegenARM64(graph, *features_arm64.get(), compiler_options);
24658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(&codegenARM64, graph, hook_before_codegen, has_result, expected);
247751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  } else if (target_isa == kX86) {
248fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
249fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell        X86InstructionSetFeatures::FromCppDefines());
250fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell    x86::CodeGeneratorX86 codegenX86(graph, *features_x86.get(), compiler_options);
25158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(&codegenX86, graph, hook_before_codegen, has_result, expected);
252751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  } else if (target_isa == kX86_64) {
253fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell    std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64(
254fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell        X86_64InstructionSetFeatures::FromCppDefines());
255fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell    x86_64::CodeGeneratorX86_64 codegenX86_64(graph, *features_x86_64.get(), compiler_options);
25658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(&codegenX86_64, graph, hook_before_codegen, has_result, expected);
257751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  } else if (target_isa == kMips) {
258f652cecb984c104d44a0223c3c98400ef8ed8ce2Goran Jakovljevic    std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
259f652cecb984c104d44a0223c3c98400ef8ed8ce2Goran Jakovljevic        MipsInstructionSetFeatures::FromCppDefines());
260f652cecb984c104d44a0223c3c98400ef8ed8ce2Goran Jakovljevic    mips::CodeGeneratorMIPS codegenMIPS(graph, *features_mips.get(), compiler_options);
26158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(&codegenMIPS, graph, hook_before_codegen, has_result, expected);
262751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  } else if (target_isa == kMips64) {
2634dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    std::unique_ptr<const Mips64InstructionSetFeatures> features_mips64(
2644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze        Mips64InstructionSetFeatures::FromCppDefines());
2654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    mips64::CodeGeneratorMIPS64 codegenMIPS64(graph, *features_mips64.get(), compiler_options);
26658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(&codegenMIPS64, graph, hook_before_codegen, has_result, expected);
267360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  }
268360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
269360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
27058282f4510961317b8d5a364a6f740a78926716fDavid Brazdilstatic ::std::vector<InstructionSet> GetTargetISAs() {
27158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  ::std::vector<InstructionSet> v;
27258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  // Add all ISAs that are executable on hardware or on simulator.
27358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  const ::std::vector<InstructionSet> executable_isa_candidates = {
27458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    kArm,
27558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    kArm64,
27658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    kThumb2,
27758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    kX86,
27858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    kX86_64,
27958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    kMips,
28058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    kMips64
28158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  };
28258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
28358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (auto target_isa : executable_isa_candidates) {
28458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    if (CanExecute(target_isa)) {
28558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      v.push_back(target_isa);
28658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    }
28758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  }
28858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
28958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  return v;
29058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil}
29158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
29258282f4510961317b8d5a364a6f740a78926716fDavid Brazdilstatic void TestCode(const uint16_t* data,
293751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                     bool has_result = false,
294751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                     int32_t expected = 0) {
29558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (InstructionSet target_isa : GetTargetISAs()) {
29658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    ArenaPool pool;
29758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    ArenaAllocator arena(&pool);
298badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    HGraph* graph = CreateCFG(&arena, data);
29958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // Remove suspend checks, they cannot be executed in this context.
30058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RemoveSuspendChecks(graph);
30158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
30258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  }
30358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil}
30458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
30558282f4510961317b8d5a364a6f740a78926716fDavid Brazdilstatic void TestCodeLong(const uint16_t* data,
306751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                         bool has_result,
307751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                         int64_t expected) {
30858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (InstructionSet target_isa : GetTargetISAs()) {
30958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    ArenaPool pool;
31058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    ArenaAllocator arena(&pool);
311badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    HGraph* graph = CreateCFG(&arena, data, Primitive::kPrimLong);
31258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // Remove suspend checks, they cannot be executed in this context.
31358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RemoveSuspendChecks(graph);
31458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
31558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  }
31655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain}
31755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
31858282f4510961317b8d5a364a6f740a78926716fDavid Brazdilclass CodegenTest : public CommonCompilerTest {};
319751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
32058282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnVoid) {
3213ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID);
32258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data);
323d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
324d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
32558282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, CFG1) {
3263ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
327d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
3283ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::RETURN_VOID);
329d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
33058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data);
331d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
332d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
33358282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, CFG2) {
3343ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
335d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
336d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
3373ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::RETURN_VOID);
338d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
33958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data);
340d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
341d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
34258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, CFG3) {
3433ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
344d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x200,
345d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
3463ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO | 0xFF00);
347d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
34858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data1);
349d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
3503ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
351d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO_16, 3,
352d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
3533ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO_16, 0xFFFF);
354d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
35558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data2);
356d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
3573ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
358d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO_32, 4, 0,
359d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
3603ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO_32, 0xFFFF, 0xFFFF);
361d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
36258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data3);
363d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
364d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
36558282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, CFG4) {
3663ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
367d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
368d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
3693ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO | 0xFE00);
370d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
37158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data);
372d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
373d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
37458282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, CFG5) {
375bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
376bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
377bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ, 3,
378bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::GOTO | 0x100,
379bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN_VOID);
380bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
38158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data);
382bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
383bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
38458282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, IntConstant) {
385bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
386bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
387bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN_VOID);
388bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
38958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data);
390bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
391bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
39258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, Return1) {
393bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
394bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
395bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0);
396bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
39758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 0);
398bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
399bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
40058282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, Return2) {
401bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
402bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
403bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 1 << 8,
404bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
405bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
40658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 0);
407bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
408bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
40958282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, Return3) {
410bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
411bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
412bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
413bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
414bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
41558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 1);
416bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
417bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
41858282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnIf1) {
419bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
420bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
421bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
422bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ, 3,
423bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0 << 8,
424bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
425bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
42658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 1);
427bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
428bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
42958282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnIf2) {
430bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
431bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
432bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
433bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ | 0 << 4 | 1 << 8, 3,
434bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0 << 8,
435bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
436bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
43758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 0);
438bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
439bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
4401cc5f251df558b0e22cea5000626365eb644c727Roland Levillain// Exercise bit-wise (one's complement) not-int instruction.
4411cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
44258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, TEST_NAME) {                        \
4431cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  const int32_t input = INPUT;                          \
44455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t input_lo = Low16Bits(input);           \
44555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t input_hi = High16Bits(input);          \
4461cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(      \
4471cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::CONST | 0 << 8, input_lo, input_hi,  \
4481cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::NOT_INT | 1 << 8 | 0 << 12 ,         \
4491cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::RETURN | 1 << 8);                    \
4501cc5f251df558b0e22cea5000626365eb644c727Roland Levillain                                                        \
45158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, EXPECTED_OUTPUT);                \
4521cc5f251df558b0e22cea5000626365eb644c727Roland Levillain}
4531cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
4541cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus2, -2, 1)
4551cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus1, -1, 0)
4561cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt0, 0, -1)
4571cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt1, 1, -2)
45855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MIN, -2147483648, 2147483647)  // (2^31) - 1
45955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MINPlus1, -2147483647, 2147483646)  // (2^31) - 2
46055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAXMinus1, 2147483646, -2147483647)  // -(2^31) - 1
46155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAX, 2147483647, -2147483648)  // -(2^31)
4621cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
4631cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#undef NOT_INT_TEST
4641cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
46555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Exercise bit-wise (one's complement) not-long instruction.
46655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define NOT_LONG_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT)                 \
46758282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, TEST_NAME) {                                         \
46855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const int64_t input = INPUT;                                           \
46955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));   /* LSW. */       \
47055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));                   \
47155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));                   \
47255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word3 = High16Bits(High32Bits(input)); /* MSW. */       \
47355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(                      \
47455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,      \
47555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::NOT_LONG | 2 << 8 | 0 << 12,                          \
47655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::RETURN_WIDE | 2 << 8);                                \
47755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                                                                         \
47858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCodeLong(data, true, EXPECTED_OUTPUT);                             \
47955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain}
48055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
48155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus2, INT64_C(-2), INT64_C(1))
48255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus1, INT64_C(-1), INT64_C(0))
48355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong0, INT64_C(0), INT64_C(-1))
48455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong1, INT64_C(1), INT64_C(-2))
48555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
48655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MIN,
48755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483648),
48855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483647))  // (2^31) - 1
48955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MINPlus1,
49055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483647),
49155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483646))  // (2^31) - 2
49255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAXMinus1,
49355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483646),
49455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483647))  // -(2^31) - 1
49555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAX,
49655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483647),
49755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483648))  // -(2^31)
49855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
49955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Note that the C++ compiler won't accept
50055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// INT64_C(-9223372036854775808) (that is, INT64_MIN) as a valid
50155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// int64_t literal, so we use INT64_C(-9223372036854775807)-1 instead.
50255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MIN,
50355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807)-1,
50455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775807));  // (2^63) - 1
50555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MINPlus1,
50655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807),
50755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775806));  // (2^63) - 2
50855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAXMinus1,
50955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775806),
51055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807));  // -(2^63) - 1
51155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAX,
51255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775807),
51355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807)-1);  // -(2^63)
51455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
51555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#undef NOT_LONG_TEST
51655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
51758282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, IntToLongOfLongToInt) {
518946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const int64_t input = INT64_C(4294967296);             // 2^32
519946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));    // LSW.
520946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));
521946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));
522946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word3 = High16Bits(High32Bits(input));  // MSW.
523946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t data[] = FIVE_REGISTERS_CODE_ITEM(
524946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
525946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::CONST_WIDE | 2 << 8, 1, 0, 0, 0,
526946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::ADD_LONG | 0, 0 << 8 | 2,             // v0 <- 2^32 + 1
527946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::LONG_TO_INT | 4 << 8 | 0 << 12,
528946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::INT_TO_LONG | 2 << 8 | 4 << 12,
529946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::RETURN_WIDE | 2 << 8);
530946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain
53158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCodeLong(data, true, 1);
532946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain}
533946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain
53458282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnAdd1) {
535d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
536d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
537d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
538d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT, 1 << 8 | 0,
539d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
540d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
54158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 7);
542d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
543d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
54458282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnAdd2) {
545d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
546d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
547d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
548d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_2ADDR | 1 << 12,
549d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
550d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
55158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 7);
552d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
553d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
55458282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnAdd3) {
555d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
556d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0 << 8,
557d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_LIT8, 3 << 8 | 0,
558d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
559d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
56058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 7);
561d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
562d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
56358282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnAdd4) {
564d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
565d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0 << 8,
566d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_LIT16, 3,
567d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
568d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
56958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 7);
570360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
571360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
57258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnMulInt) {
5735da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
5745da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
5755da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
5765da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::MUL_INT, 1 << 8 | 0,
5775da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::RETURN);
5785da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
57958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 12);
5805da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray}
5815da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
58258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnMulInt2addr) {
5835da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
5845da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
5855da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
5865da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::MUL_INT_2ADDR | 1 << 12,
5875da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::RETURN);
58834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
58958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 12);
5905da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray}
5915da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
59258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnMulLong) {
5935da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray  const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(
59458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    Instruction::CONST_WIDE | 0 << 8, 3, 0, 0, 0,
59558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    Instruction::CONST_WIDE | 2 << 8, 4, 0, 0, 0,
5965da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::MUL_LONG, 2 << 8 | 0,
5975da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::RETURN_WIDE);
5985da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
59958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCodeLong(data, true, 12);
6005da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray}
6015da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
60258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnMulLong2addr) {
6035da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray  const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(
60458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    Instruction::CONST_WIDE | 0 << 8, 3, 0, 0, 0,
60558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    Instruction::CONST_WIDE | 2 << 8, 4, 0, 0, 0,
6065da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::MUL_LONG_2ADDR | 2 << 12,
6075da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray    Instruction::RETURN_WIDE);
6085da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray
60958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCodeLong(data, true, 12);
6105da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray}
61134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
61258282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnMulIntLit8) {
61334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
61434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
61534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::MUL_INT_LIT8, 3 << 8 | 0,
61634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::RETURN);
61734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
61858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 12);
61934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle}
62034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
62158282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnMulIntLit16) {
62234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
62334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
62434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::MUL_INT_LIT16, 3,
62534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::RETURN);
62634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
62758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 12);
62834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle}
62934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
63058282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, NonMaterializedCondition) {
63158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (InstructionSet target_isa : GetTargetISAs()) {
632927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaPool pool;
633927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaAllocator allocator(&pool);
634927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
63558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HGraph* graph = CreateGraph(&allocator);
636badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil
63758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
63858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    graph->AddBlock(entry);
63958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    graph->SetEntryBlock(entry);
64058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    entry->AddInstruction(new (&allocator) HGoto());
64158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
64258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HBasicBlock* first_block = new (&allocator) HBasicBlock(graph);
64358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    graph->AddBlock(first_block);
64458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    entry->AddSuccessor(first_block);
64558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HIntConstant* constant0 = graph->GetIntConstant(0);
64658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HIntConstant* constant1 = graph->GetIntConstant(1);
64758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HEqual* equal = new (&allocator) HEqual(constant0, constant0);
64858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    first_block->AddInstruction(equal);
64958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    first_block->AddInstruction(new (&allocator) HIf(equal));
65058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
65158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HBasicBlock* then_block = new (&allocator) HBasicBlock(graph);
65258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    HBasicBlock* else_block = new (&allocator) HBasicBlock(graph);
653927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
65458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    graph->SetExitBlock(exit_block);
65558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
65658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    graph->AddBlock(then_block);
65758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    graph->AddBlock(else_block);
658927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(exit_block);
65958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    first_block->AddSuccessor(then_block);
66058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    first_block->AddSuccessor(else_block);
66158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    then_block->AddSuccessor(exit_block);
66258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    else_block->AddSuccessor(exit_block);
663927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
66458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    exit_block->AddInstruction(new (&allocator) HExit());
66558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    then_block->AddInstruction(new (&allocator) HReturn(constant0));
66658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    else_block->AddInstruction(new (&allocator) HReturn(constant1));
667927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
668b11b0725d02aafd6e3ea4eb514b215149c893bf0David Brazdil    ASSERT_FALSE(equal->IsEmittedAtUseSite());
669badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil    graph->BuildDominatorTree();
67058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    PrepareForRegisterAllocation(graph).Run();
671b11b0725d02aafd6e3ea4eb514b215149c893bf0David Brazdil    ASSERT_TRUE(equal->IsEmittedAtUseSite());
672927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
673277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    auto hook_before_codegen = [](HGraph* graph_in) {
674ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
675277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
676927307433af0a9322e8ba77eda37168512a73683Alexandre Rames      block->InsertInstructionBefore(move, block->GetLastInstruction());
677927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    };
678927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
67958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    RunCode(target_isa, graph, hook_before_codegen, true, 0);
680927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  }
681927307433af0a9322e8ba77eda37168512a73683Alexandre Rames}
682927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
68358282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, MaterializedCondition1) {
68458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (InstructionSet target_isa : GetTargetISAs()) {
68558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // Check that condition are materialized correctly. A materialized condition
68658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // should yield `1` if it evaluated to true, and `0` otherwise.
68758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // We force the materialization of comparisons for different combinations of
68858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
68958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // inputs and check the results.
69058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
69158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    int lhs[] = {1, 2, -1, 2, 0xabc};
69258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    int rhs[] = {2, 1, 2, -1, 0xabc};
69358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
69458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    for (size_t i = 0; i < arraysize(lhs); i++) {
69558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      ArenaPool pool;
69658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      ArenaAllocator allocator(&pool);
69758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HGraph* graph = CreateGraph(&allocator);
69858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
69958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
70058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(entry_block);
70158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->SetEntryBlock(entry_block);
70258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      entry_block->AddInstruction(new (&allocator) HGoto());
70358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* code_block = new (&allocator) HBasicBlock(graph);
70458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(code_block);
70558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
70658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(exit_block);
70758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      exit_block->AddInstruction(new (&allocator) HExit());
70858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
70958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      entry_block->AddSuccessor(code_block);
71058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      code_block->AddSuccessor(exit_block);
71158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->SetExitBlock(exit_block);
71258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
71358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]);
71458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
71558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HLessThan cmp_lt(cst_lhs, cst_rhs);
71658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      code_block->AddInstruction(&cmp_lt);
71758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HReturn ret(&cmp_lt);
71858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      code_block->AddInstruction(&ret);
71958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
720badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      graph->BuildDominatorTree();
72158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      auto hook_before_codegen = [](HGraph* graph_in) {
72258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
72358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
72458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        block->InsertInstructionBefore(move, block->GetLastInstruction());
72558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      };
72658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
72758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    }
72858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  }
72958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil}
730927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
73158282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, MaterializedCondition2) {
73258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (InstructionSet target_isa : GetTargetISAs()) {
73358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // Check that HIf correctly interprets a materialized condition.
73458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // We force the materialization of comparisons for different combinations of
73558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // inputs. An HIf takes the materialized combination as input and returns a
73658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    // value that we verify.
73758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
73858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    int lhs[] = {1, 2, -1, 2, 0xabc};
73958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    int rhs[] = {2, 1, 2, -1, 0xabc};
74058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
74158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
74258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    for (size_t i = 0; i < arraysize(lhs); i++) {
74358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      ArenaPool pool;
74458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      ArenaAllocator allocator(&pool);
74558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HGraph* graph = CreateGraph(&allocator);
74658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
74758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
74858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(entry_block);
74958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->SetEntryBlock(entry_block);
75058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      entry_block->AddInstruction(new (&allocator) HGoto());
75158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
75258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* if_block = new (&allocator) HBasicBlock(graph);
75358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(if_block);
75458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* if_true_block = new (&allocator) HBasicBlock(graph);
75558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(if_true_block);
75658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* if_false_block = new (&allocator) HBasicBlock(graph);
75758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(if_false_block);
75858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
75958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->AddBlock(exit_block);
76058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      exit_block->AddInstruction(new (&allocator) HExit());
76158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
76258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->SetEntryBlock(entry_block);
76358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      entry_block->AddSuccessor(if_block);
76458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_block->AddSuccessor(if_true_block);
76558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_block->AddSuccessor(if_false_block);
76658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_true_block->AddSuccessor(exit_block);
76758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_false_block->AddSuccessor(exit_block);
76858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      graph->SetExitBlock(exit_block);
76958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
77058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]);
77158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
77258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HLessThan cmp_lt(cst_lhs, cst_rhs);
77358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_block->AddInstruction(&cmp_lt);
7746e332529c33be4d7dae5dad3609a839f4c0d3bfcDavid Brazdil      // We insert a dummy instruction to separate the HIf from the HLessThan
7756e332529c33be4d7dae5dad3609a839f4c0d3bfcDavid Brazdil      // and force the materialization of the condition.
7766e332529c33be4d7dae5dad3609a839f4c0d3bfcDavid Brazdil      HMemoryBarrier force_materialization(MemBarrierKind::kAnyAny, 0);
77758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_block->AddInstruction(&force_materialization);
77858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HIf if_lt(&cmp_lt);
77958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_block->AddInstruction(&if_lt);
78058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
78158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HIntConstant* cst_lt = graph->GetIntConstant(1);
78258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HReturn ret_lt(cst_lt);
78358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_true_block->AddInstruction(&ret_lt);
78458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HIntConstant* cst_ge = graph->GetIntConstant(0);
78558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      HReturn ret_ge(cst_ge);
78658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      if_false_block->AddInstruction(&ret_ge);
78758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
788badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil      graph->BuildDominatorTree();
78958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      auto hook_before_codegen = [](HGraph* graph_in) {
79058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
79158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
79258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        block->InsertInstructionBefore(move, block->GetLastInstruction());
79358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      };
79458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
79558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    }
796927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  }
797927307433af0a9322e8ba77eda37168512a73683Alexandre Rames}
79834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
79958282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnDivIntLit8) {
800d0d4852847432368b090c184d6639e573538dccfCalin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
801d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
802d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::DIV_INT_LIT8, 3 << 8 | 0,
803d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::RETURN);
804d0d4852847432368b090c184d6639e573538dccfCalin Juravle
80558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 1);
806d0d4852847432368b090c184d6639e573538dccfCalin Juravle}
807d0d4852847432368b090c184d6639e573538dccfCalin Juravle
80858282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ReturnDivInt2Addr) {
809865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
810865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0,
811865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::CONST_4 | 2 << 12 | 1 << 8,
812865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::DIV_INT_2ADDR | 1 << 12,
813865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::RETURN);
814865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle
81558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  TestCode(data, true, 2);
816865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle}
817865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle
818e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik// Helper method.
819751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wangstatic void TestComparison(IfCondition condition,
820751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                           int64_t i,
821751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                           int64_t j,
822751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                           Primitive::Type type,
823751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang                           const InstructionSet target_isa) {
824e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  ArenaPool pool;
825e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  ArenaAllocator allocator(&pool);
826e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  HGraph* graph = CreateGraph(&allocator);
827e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
828e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
829e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  graph->AddBlock(entry_block);
830e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  graph->SetEntryBlock(entry_block);
831e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  entry_block->AddInstruction(new (&allocator) HGoto());
832e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
833e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  HBasicBlock* block = new (&allocator) HBasicBlock(graph);
834e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  graph->AddBlock(block);
835e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
836e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
837e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  graph->AddBlock(exit_block);
838e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  graph->SetExitBlock(exit_block);
839e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  exit_block->AddInstruction(new (&allocator) HExit());
840e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
841e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  entry_block->AddSuccessor(block);
842e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  block->AddSuccessor(exit_block);
843e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
844e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  HInstruction* op1;
845e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  HInstruction* op2;
846e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  if (type == Primitive::kPrimInt) {
847e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    op1 = graph->GetIntConstant(i);
848e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    op2 = graph->GetIntConstant(j);
849e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  } else {
850e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    DCHECK_EQ(type, Primitive::kPrimLong);
851e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    op1 = graph->GetLongConstant(i);
852e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    op2 = graph->GetLongConstant(j);
853e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  }
854e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
855e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  HInstruction* comparison = nullptr;
856e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  bool expected_result = false;
857e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  const uint64_t x = i;
858e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  const uint64_t y = j;
859e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  switch (condition) {
860e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondEQ:
861e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HEqual(op1, op2);
862e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (i == j);
863e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
864e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondNE:
865e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HNotEqual(op1, op2);
866e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (i != j);
867e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
868e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondLT:
869e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HLessThan(op1, op2);
870e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (i < j);
871e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
872e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondLE:
873e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HLessThanOrEqual(op1, op2);
874e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (i <= j);
875e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
876e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondGT:
877e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HGreaterThan(op1, op2);
878e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (i > j);
879e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
880e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondGE:
881e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HGreaterThanOrEqual(op1, op2);
882e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (i >= j);
883e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
884e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondB:
885e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HBelow(op1, op2);
886e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (x < y);
887e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
888e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondBE:
889e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HBelowOrEqual(op1, op2);
890e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (x <= y);
891e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
892e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondA:
893e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HAbove(op1, op2);
894e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (x > y);
895e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
896e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    case kCondAE:
897e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      comparison = new (&allocator) HAboveOrEqual(op1, op2);
898e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      expected_result = (x >= y);
899e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik      break;
900e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  }
901e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  block->AddInstruction(comparison);
902e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  block->AddInstruction(new (&allocator) HReturn(comparison));
903e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
904badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  graph->BuildDominatorTree();
90558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  RunCode(target_isa, graph, [](HGraph*) {}, true, expected_result);
90658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil}
90758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil
90858282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ComparisonsInt) {
90958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (InstructionSet target_isa : GetTargetISAs()) {
91058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    for (int64_t i = -1; i <= 1; i++) {
91158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      for (int64_t j = -1; j <= 1; j++) {
91258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondEQ, i, j, Primitive::kPrimInt, target_isa);
91358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondNE, i, j, Primitive::kPrimInt, target_isa);
91458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondLT, i, j, Primitive::kPrimInt, target_isa);
91558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondLE, i, j, Primitive::kPrimInt, target_isa);
91658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondGT, i, j, Primitive::kPrimInt, target_isa);
91758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondGE, i, j, Primitive::kPrimInt, target_isa);
91858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondB,  i, j, Primitive::kPrimInt, target_isa);
91958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondBE, i, j, Primitive::kPrimInt, target_isa);
92058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondA,  i, j, Primitive::kPrimInt, target_isa);
92158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondAE, i, j, Primitive::kPrimInt, target_isa);
92258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      }
923e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    }
924e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  }
925e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik}
926e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
92758282f4510961317b8d5a364a6f740a78926716fDavid BrazdilTEST_F(CodegenTest, ComparisonsLong) {
928e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  // TODO: make MIPS work for long
929e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  if (kRuntimeISA == kMips || kRuntimeISA == kMips64) {
930e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    return;
931e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik  }
932e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
93358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  for (InstructionSet target_isa : GetTargetISAs()) {
93458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    if (target_isa == kMips || target_isa == kMips64) {
93558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      continue;
936e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik    }
937e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik
93858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil    for (int64_t i = -1; i <= 1; i++) {
93958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      for (int64_t j = -1; j <= 1; j++) {
94058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondEQ, i, j, Primitive::kPrimLong, target_isa);
94158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondNE, i, j, Primitive::kPrimLong, target_isa);
94258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondLT, i, j, Primitive::kPrimLong, target_isa);
94358282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondLE, i, j, Primitive::kPrimLong, target_isa);
94458282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondGT, i, j, Primitive::kPrimLong, target_isa);
94558282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondGE, i, j, Primitive::kPrimLong, target_isa);
94658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondB,  i, j, Primitive::kPrimLong, target_isa);
94758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondBE, i, j, Primitive::kPrimLong, target_isa);
94858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondA,  i, j, Primitive::kPrimLong, target_isa);
94958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil        TestComparison(kCondAE, i, j, Primitive::kPrimLong, target_isa);
95058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil      }
951751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang    }
952751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang  }
953751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang}
954751beff19b36f777d9e3a966d754fd9cfad5d534Phil Wang
955d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
956