codegen_test.cc revision 3416601a9e9be81bb7494864287fd3602d18ef13
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"
30d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h"
313ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#include "optimizing_unit_test.h"
32360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "prepare_for_register_allocation.h"
33360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "register_allocator.h"
34360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "ssa_liveness_analysis.h"
3555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#include "utils.h"
36d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
37d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "gtest/gtest.h"
38d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
39d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art {
40d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
41787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass InternalCodeAllocator : public CodeAllocator {
42d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
43d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  InternalCodeAllocator() : size_(0) { }
44d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
45d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) {
46787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray    size_ = size;
47d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    memory_.reset(new uint8_t[size]);
48d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    return memory_.get();
49d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  }
50d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
51787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  size_t GetSize() const { return size_; }
52787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint8_t* GetMemory() const { return memory_.get(); }
53d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
54d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
55787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  size_t size_;
56700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<uint8_t[]> memory_;
57d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
58787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
59d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
60d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
6155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
628d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffraystatic void Run(const InternalCodeAllocator& allocator,
638d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray                const CodeGenerator& codegen,
648d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray                bool has_result,
6555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                Expected expected) {
6655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  typedef Expected (*fptr)();
679cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray  CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize());
6820dfc797dc631bf8d655dcf123f46f13332d3074Dave Allison  fptr f = reinterpret_cast<fptr>(allocator.GetMemory());
698d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray  if (codegen.GetInstructionSet() == kThumb2) {
708d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray    // For thumb we need the bottom bit set.
718d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray    f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1);
728d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray  }
7355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  Expected result = f();
749cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray  if (has_result) {
75360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    ASSERT_EQ(result, expected);
769cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray  }
779cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray}
789cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
7955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
8055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillainstatic void RunCodeBaseline(HGraph* graph, bool has_result, Expected expected) {
81787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  InternalCodeAllocator allocator;
829cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
838a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  x86::CodeGeneratorX86 codegenX86(graph);
8473e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  // We avoid doing a stack overflow check that requires the runtime being setup,
8573e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  // by making sure the compiler knows the methods we are running are leaf methods.
868a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  codegenX86.CompileBaseline(&allocator, true);
878a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  if (kRuntimeISA == kX86) {
888a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray    Run(allocator, codegenX86, has_result, expected);
898a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  }
909cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
913416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle  arm::CodeGeneratorARM codegenARM(graph, ArmInstructionSetFeatures::FromCppDefines());
928a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  codegenARM.CompileBaseline(&allocator, true);
938a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
948a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray    Run(allocator, codegenARM, has_result, expected);
958a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  }
969cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray
978a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  x86_64::CodeGeneratorX86_64 codegenX86_64(graph);
988a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  codegenX86_64.CompileBaseline(&allocator, true);
998a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  if (kRuntimeISA == kX86_64) {
1008a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray    Run(allocator, codegenX86_64, has_result, expected);
1018a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray  }
1025319defdf502fc4569316473846b83180ec08035Alexandre Rames
1035319defdf502fc4569316473846b83180ec08035Alexandre Rames  arm64::CodeGeneratorARM64 codegenARM64(graph);
1045319defdf502fc4569316473846b83180ec08035Alexandre Rames  codegenARM64.CompileBaseline(&allocator, true);
1055319defdf502fc4569316473846b83180ec08035Alexandre Rames  if (kRuntimeISA == kArm64) {
1065319defdf502fc4569316473846b83180ec08035Alexandre Rames    Run(allocator, codegenARM64, has_result, expected);
1075319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
108d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
109d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
11055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
111360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void RunCodeOptimized(CodeGenerator* codegen,
112360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             HGraph* graph,
113360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             std::function<void(HGraph*)> hook_before_codegen,
114360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             bool has_result,
11555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                             Expected expected) {
116360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  SsaLivenessAnalysis liveness(*graph, codegen);
117360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  liveness.Analyze();
118360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
119360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness);
120360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  register_allocator.AllocateRegisters();
121360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  hook_before_codegen(graph);
122360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
123360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  InternalCodeAllocator allocator;
124360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  codegen->CompileOptimized(&allocator);
125360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  Run(allocator, *codegen, has_result, expected);
126360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
127360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
12855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected>
129360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void RunCodeOptimized(HGraph* graph,
130360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             std::function<void(HGraph*)> hook_before_codegen,
131360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray                             bool has_result,
13255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                             Expected expected) {
1333e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
1343416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle    arm::CodeGeneratorARM codegenARM(graph, ArmInstructionSetFeatures::FromCppDefines());
135360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    RunCodeOptimized(&codegenARM, graph, hook_before_codegen, has_result, expected);
1363e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  } else if (kRuntimeISA == kArm64) {
1373e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    arm64::CodeGeneratorARM64 codegenARM64(graph);
1383e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    RunCodeOptimized(&codegenARM64, graph, hook_before_codegen, has_result, expected);
1393e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  } else if (kRuntimeISA == kX86) {
1403e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    x86::CodeGeneratorX86 codegenX86(graph);
1413e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    RunCodeOptimized(&codegenX86, graph, hook_before_codegen, has_result, expected);
142360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  } else if (kRuntimeISA == kX86_64) {
143360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    x86_64::CodeGeneratorX86_64 codegenX86_64(graph);
144360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    RunCodeOptimized(&codegenX86_64, graph, hook_before_codegen, has_result, expected);
145360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  }
146360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
147360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
148360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) {
149360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaPool pool;
150360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaAllocator arena(&pool);
151360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HGraphBuilder builder(&arena);
152360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
153360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HGraph* graph = builder.BuildGraph(*item);
154360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ASSERT_NE(graph, nullptr);
155039b6e2fd3bfadbd1ee8583002f673d6ccba5b7eCalin Juravle  // Remove suspend checks, they cannot be executed in this context.
15648dee04f4e4214b0fdd8acd0587ef6b08d3d2456Calin Juravle  RemoveSuspendChecks(graph);
157360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  RunCodeBaseline(graph, has_result, expected);
158360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
159360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
16055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillainstatic void TestCodeLong(const uint16_t* data, bool has_result, int64_t expected) {
16155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  ArenaPool pool;
16255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  ArenaAllocator arena(&pool);
16355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  HGraphBuilder builder(&arena, Primitive::kPrimLong);
16455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
16555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  HGraph* graph = builder.BuildGraph(*item);
16655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  ASSERT_NE(graph, nullptr);
16755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  // Remove suspend checks, they cannot be executed in this context.
16855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  RemoveSuspendChecks(graph);
16955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  RunCodeBaseline(graph, has_result, expected);
17055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain}
17155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
172d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas GeoffrayTEST(CodegenTest, ReturnVoid) {
1733ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID);
1743ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
175d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
176d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
177bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG1) {
1783ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
179d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
1803ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::RETURN_VOID);
181d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
1823ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
183d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
184d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
185bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG2) {
1863ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
187d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
188d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
1893ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::RETURN_VOID);
190d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
1913ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
192d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
193d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
194bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG3) {
1953ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
196d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x200,
197d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
1983ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO | 0xFF00);
199d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2003ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data1);
201d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2023ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
203d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO_16, 3,
204d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
2053ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO_16, 0xFFFF);
206d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2073ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data2);
208d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2093ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
210d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO_32, 4, 0,
211d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
2123ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO_32, 0xFFFF, 0xFFFF);
213d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2143ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data3);
215d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
216d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
217bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG4) {
2183ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
219d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::RETURN_VOID,
220d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray    Instruction::GOTO | 0x100,
2213ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray    Instruction::GOTO | 0xFE00);
222d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2233ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray  TestCode(data);
224d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}
225d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
226bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG5) {
227bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
228bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
229bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ, 3,
230bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::GOTO | 0x100,
231bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN_VOID);
232bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
233bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data);
234bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
235bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
236bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, IntConstant) {
237bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
238bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
239bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN_VOID);
240bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
241bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data);
242bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
243bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
244bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return1) {
245bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
246bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
247bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0);
248bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
249bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 0);
250bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
251bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
252bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return2) {
253bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
254bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
255bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 1 << 8,
256bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
257bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
258bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 0);
259bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
260bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
261bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return3) {
262bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
263bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
264bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
265bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
266bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
267bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 1);
268bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
269bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
270bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, ReturnIf1) {
271bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
272bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
273bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
274bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ, 3,
275bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0 << 8,
276bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
277bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
278bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 1);
279bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
280bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
281bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, ReturnIf2) {
282bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
283bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
284bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::CONST_4 | 1 << 8 | 1 << 12,
285bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::IF_EQ | 0 << 4 | 1 << 8, 3,
286bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 0 << 8,
287bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray    Instruction::RETURN | 1 << 8);
288bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
289bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  TestCode(data, true, 0);
290bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}
291bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
2921cc5f251df558b0e22cea5000626365eb644c727Roland Levillain// Exercise bit-wise (one's complement) not-int instruction.
2931cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
2941cc5f251df558b0e22cea5000626365eb644c727Roland LevillainTEST(CodegenTest, TEST_NAME) {                          \
2951cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  const int32_t input = INPUT;                          \
29655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t input_lo = Low16Bits(input);           \
29755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t input_hi = High16Bits(input);          \
2981cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(      \
2991cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::CONST | 0 << 8, input_lo, input_hi,  \
3001cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::NOT_INT | 1 << 8 | 0 << 12 ,         \
3011cc5f251df558b0e22cea5000626365eb644c727Roland Levillain      Instruction::RETURN | 1 << 8);                    \
3021cc5f251df558b0e22cea5000626365eb644c727Roland Levillain                                                        \
3031cc5f251df558b0e22cea5000626365eb644c727Roland Levillain  TestCode(data, true, EXPECTED_OUTPUT);                \
3041cc5f251df558b0e22cea5000626365eb644c727Roland Levillain}
3051cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
3061cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus2, -2, 1)
3071cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus1, -1, 0)
3081cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt0, 0, -1)
3091cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt1, 1, -2)
31055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MIN, -2147483648, 2147483647)  // (2^31) - 1
31155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MINPlus1, -2147483647, 2147483646)  // (2^31) - 2
31255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAXMinus1, 2147483646, -2147483647)  // -(2^31) - 1
31355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAX, 2147483647, -2147483648)  // -(2^31)
3141cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
3151cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#undef NOT_INT_TEST
3161cc5f251df558b0e22cea5000626365eb644c727Roland Levillain
31755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Exercise bit-wise (one's complement) not-long instruction.
31855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define NOT_LONG_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT)                 \
31955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainTEST(CodegenTest, TEST_NAME) {                                           \
32055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const int64_t input = INPUT;                                           \
32155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));   /* LSW. */       \
32255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));                   \
32355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));                   \
32455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t word3 = High16Bits(High32Bits(input)); /* MSW. */       \
32555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(                      \
32655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,      \
32755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::NOT_LONG | 2 << 8 | 0 << 12,                          \
32855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain      Instruction::RETURN_WIDE | 2 << 8);                                \
32955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain                                                                         \
33055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain  TestCodeLong(data, true, EXPECTED_OUTPUT);                             \
33155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain}
33255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
33355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus2, INT64_C(-2), INT64_C(1))
33455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus1, INT64_C(-1), INT64_C(0))
33555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong0, INT64_C(0), INT64_C(-1))
33655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong1, INT64_C(1), INT64_C(-2))
33755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
33855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MIN,
33955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483648),
34055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483647))  // (2^31) - 1
34155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MINPlus1,
34255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483647),
34355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483646))  // (2^31) - 2
34455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAXMinus1,
34555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483646),
34655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483647))  // -(2^31) - 1
34755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAX,
34855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(2147483647),
34955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-2147483648))  // -(2^31)
35055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
35155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Note that the C++ compiler won't accept
35255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// INT64_C(-9223372036854775808) (that is, INT64_MIN) as a valid
35355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// int64_t literal, so we use INT64_C(-9223372036854775807)-1 instead.
35455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MIN,
35555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807)-1,
35655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775807));  // (2^63) - 1
35755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MINPlus1,
35855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807),
35955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775806));  // (2^63) - 2
36055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAXMinus1,
36155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775806),
36255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807));  // -(2^63) - 1
36355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAX,
36455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(9223372036854775807),
36555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain              INT64_C(-9223372036854775807)-1);  // -(2^63)
36655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
36755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#undef NOT_LONG_TEST
36855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain
369946e143941d456a4ec666f7f54719c65c5aa3f5dRoland LevillainTEST(CodegenTest, IntToLongOfLongToInt) {
370946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const int64_t input = INT64_C(4294967296);             // 2^32
371946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));    // LSW.
372946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));
373946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));
374946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t word3 = High16Bits(High32Bits(input));  // MSW.
375946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  const uint16_t data[] = FIVE_REGISTERS_CODE_ITEM(
376946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
377946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::CONST_WIDE | 2 << 8, 1, 0, 0, 0,
378946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::ADD_LONG | 0, 0 << 8 | 2,             // v0 <- 2^32 + 1
379946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::LONG_TO_INT | 4 << 8 | 0 << 12,
380946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::INT_TO_LONG | 2 << 8 | 4 << 12,
381946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain      Instruction::RETURN_WIDE | 2 << 8);
382946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain
383946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain  TestCodeLong(data, true, 1);
384946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain}
385946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain
386d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd1) {
387d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
388d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
389d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
390d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT, 1 << 8 | 0,
391d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
392d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
393d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
394d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
395d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
396d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd2) {
397d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
398d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 3 << 12 | 0,
399d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
400d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_2ADDR | 1 << 12,
401d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
402d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
403d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
404d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
405d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
406d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd3) {
407d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
408d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0 << 8,
409d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_LIT8, 3 << 8 | 0,
410d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
411d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
412d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
413d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
414d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
415d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd4) {
416d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
417d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0 << 8,
418d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::ADD_INT_LIT16, 3,
419d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray    Instruction::RETURN);
420d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
421d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray  TestCode(data, true, 7);
422d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray}
423d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray
424360231a056e796c36ffe62348507e904dc9efb9bNicolas GeoffrayTEST(CodegenTest, NonMaterializedCondition) {
425360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaPool pool;
426360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ArenaAllocator allocator(&pool);
427360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
428360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HGraph* graph = new (&allocator) HGraph(&allocator);
429360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
430360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(entry);
431360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->SetEntryBlock(entry);
432360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddInstruction(new (&allocator) HGoto());
433360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
434360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* first_block = new (&allocator) HBasicBlock(graph);
435360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(first_block);
436360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddSuccessor(first_block);
437360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HIntConstant* constant0 = new (&allocator) HIntConstant(0);
438360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddInstruction(constant0);
439360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HIntConstant* constant1 = new (&allocator) HIntConstant(1);
440360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  entry->AddInstruction(constant1);
441360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HEqual* equal = new (&allocator) HEqual(constant0, constant0);
442360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddInstruction(equal);
443360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddInstruction(new (&allocator) HIf(equal));
444360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
445360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* then = new (&allocator) HBasicBlock(graph);
446360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
447360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
448360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
449360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(then);
450360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(else_);
451360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->AddBlock(exit);
452360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddSuccessor(then);
453360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  first_block->AddSuccessor(else_);
454360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  then->AddSuccessor(exit);
455360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  else_->AddSuccessor(exit);
456360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
457360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  exit->AddInstruction(new (&allocator) HExit());
458360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  then->AddInstruction(new (&allocator) HReturn(constant0));
459360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  else_->AddInstruction(new (&allocator) HReturn(constant1));
460360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
461360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ASSERT_TRUE(equal->NeedsMaterialization());
462360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  graph->BuildDominatorTree();
463360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  PrepareForRegisterAllocation(graph).Run();
464360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  ASSERT_FALSE(equal->NeedsMaterialization());
465360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
466277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe  auto hook_before_codegen = [](HGraph* graph_in) {
467277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
468277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
469360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray    block->InsertInstructionBefore(move, block->GetLastInstruction());
470360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  };
471360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
472360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  RunCodeOptimized(graph, hook_before_codegen, true, 0);
473360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray}
474360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray
47534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle#define MUL_TEST(TYPE, TEST_NAME)                     \
47634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TEST(CodegenTest, Return ## TEST_NAME) {            \
47734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(  \
47834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 3 << 12 | 0,             \
47934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 4 << 12 | 1 << 8,        \
48034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::MUL_ ## TYPE, 1 << 8 | 0,          \
48134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::RETURN);                           \
48234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle                                                      \
48334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    TestCode(data, true, 12);                         \
48434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  }                                                   \
48534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle                                                      \
48634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TEST(CodegenTest, Return ## TEST_NAME ## 2addr) {   \
48734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(  \
48834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 3 << 12 | 0,             \
48934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::CONST_4 | 4 << 12 | 1 << 8,        \
49034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::MUL_ ## TYPE ## _2ADDR | 1 << 12,  \
49134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle      Instruction::RETURN);                           \
49234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle                                                      \
49334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    TestCode(data, true, 12);                         \
49434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  }
49534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
49634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleMUL_TEST(INT, MulInt);
49734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleMUL_TEST(LONG, MulLong);
49834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
49934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleTEST(CodegenTest, ReturnMulIntLit8) {
50034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
50134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
50234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::MUL_INT_LIT8, 3 << 8 | 0,
50334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::RETURN);
50434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
50534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TestCode(data, true, 12);
50634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle}
50734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
50834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleTEST(CodegenTest, ReturnMulIntLit16) {
50934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
51034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
51134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::MUL_INT_LIT16, 3,
51234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle    Instruction::RETURN);
51334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
51434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle  TestCode(data, true, 12);
51534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle}
51634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
517927307433af0a9322e8ba77eda37168512a73683Alexandre RamesTEST(CodegenTest, MaterializedCondition1) {
518927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // Check that condition are materialized correctly. A materialized condition
519927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // should yield `1` if it evaluated to true, and `0` otherwise.
520927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // We force the materialization of comparisons for different combinations of
521927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // inputs and check the results.
522927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
523927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int lhs[] = {1, 2, -1, 2, 0xabc};
524927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int rhs[] = {2, 1, 2, -1, 0xabc};
525927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
526927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  for (size_t i = 0; i < arraysize(lhs); i++) {
527927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaPool pool;
528927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaAllocator allocator(&pool);
529927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HGraph* graph = new (&allocator) HGraph(&allocator);
530927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
531927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
532927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(entry_block);
533927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetEntryBlock(entry_block);
534927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddInstruction(new (&allocator) HGoto());
535927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* code_block = new (&allocator) HBasicBlock(graph);
536927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(code_block);
537927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
538927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(exit_block);
539927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    exit_block->AddInstruction(new (&allocator) HExit());
540927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
541927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddSuccessor(code_block);
542927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddSuccessor(exit_block);
543927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetExitBlock(exit_block);
544927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
545927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_lhs(lhs[i]);
546927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&cst_lhs);
547927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_rhs(rhs[i]);
548927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&cst_rhs);
549927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HLessThan cmp_lt(&cst_lhs, &cst_rhs);
550927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&cmp_lt);
551927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HReturn ret(&cmp_lt);
552927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    code_block->AddInstruction(&ret);
553927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
554277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    auto hook_before_codegen = [](HGraph* graph_in) {
555277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
556277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
557927307433af0a9322e8ba77eda37168512a73683Alexandre Rames      block->InsertInstructionBefore(move, block->GetLastInstruction());
558927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    };
559927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
560927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    RunCodeOptimized(graph, hook_before_codegen, true, lhs[i] < rhs[i]);
561927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  }
562927307433af0a9322e8ba77eda37168512a73683Alexandre Rames}
563927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
564927307433af0a9322e8ba77eda37168512a73683Alexandre RamesTEST(CodegenTest, MaterializedCondition2) {
565927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // Check that HIf correctly interprets a materialized condition.
566927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // We force the materialization of comparisons for different combinations of
567927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // inputs. An HIf takes the materialized combination as input and returns a
568927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  // value that we verify.
569927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
570927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int lhs[] = {1, 2, -1, 2, 0xabc};
571927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  int rhs[] = {2, 1, 2, -1, 0xabc};
572927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
573927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
574927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  for (size_t i = 0; i < arraysize(lhs); i++) {
575927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaPool pool;
576927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    ArenaAllocator allocator(&pool);
577927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HGraph* graph = new (&allocator) HGraph(&allocator);
578927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
579927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
580927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(entry_block);
581927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetEntryBlock(entry_block);
582927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddInstruction(new (&allocator) HGoto());
583927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
584927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* if_block = new (&allocator) HBasicBlock(graph);
585927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(if_block);
586927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* if_true_block = new (&allocator) HBasicBlock(graph);
587927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(if_true_block);
588927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* if_false_block = new (&allocator) HBasicBlock(graph);
589927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(if_false_block);
590927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
591927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->AddBlock(exit_block);
592927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    exit_block->AddInstruction(new (&allocator) HExit());
593927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
594927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetEntryBlock(entry_block);
595927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    entry_block->AddSuccessor(if_block);
596927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddSuccessor(if_true_block);
597927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddSuccessor(if_false_block);
598927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_true_block->AddSuccessor(exit_block);
599927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_false_block->AddSuccessor(exit_block);
600927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    graph->SetExitBlock(exit_block);
601927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
602927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_lhs(lhs[i]);
603927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&cst_lhs);
604927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_rhs(rhs[i]);
605927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&cst_rhs);
606927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HLessThan cmp_lt(&cst_lhs, &cst_rhs);
607927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&cmp_lt);
608927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    // We insert a temporary to separate the HIf from the HLessThan and force
609927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    // the materialization of the condition.
610927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HTemporary force_materialization(0);
611927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&force_materialization);
612927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIf if_lt(&cmp_lt);
613927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_block->AddInstruction(&if_lt);
614927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
615927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_lt(1);
616927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_true_block->AddInstruction(&cst_lt);
617927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HReturn ret_lt(&cst_lt);
618927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_true_block->AddInstruction(&ret_lt);
619927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HIntConstant cst_ge(0);
620927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_false_block->AddInstruction(&cst_ge);
621927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    HReturn ret_ge(&cst_ge);
622927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    if_false_block->AddInstruction(&ret_ge);
623927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
624277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    auto hook_before_codegen = [](HGraph* graph_in) {
625277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
626277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
627927307433af0a9322e8ba77eda37168512a73683Alexandre Rames      block->InsertInstructionBefore(move, block->GetLastInstruction());
628927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    };
629927307433af0a9322e8ba77eda37168512a73683Alexandre Rames
630927307433af0a9322e8ba77eda37168512a73683Alexandre Rames    RunCodeOptimized(graph, hook_before_codegen, true, lhs[i] < rhs[i]);
631927307433af0a9322e8ba77eda37168512a73683Alexandre Rames  }
632927307433af0a9322e8ba77eda37168512a73683Alexandre Rames}
63334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle
634d0d4852847432368b090c184d6639e573538dccfCalin JuravleTEST(CodegenTest, ReturnDivIntLit8) {
635d0d4852847432368b090c184d6639e573538dccfCalin Juravle  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
636d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::CONST_4 | 4 << 12 | 0 << 8,
637d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::DIV_INT_LIT8, 3 << 8 | 0,
638d0d4852847432368b090c184d6639e573538dccfCalin Juravle    Instruction::RETURN);
639d0d4852847432368b090c184d6639e573538dccfCalin Juravle
640d0d4852847432368b090c184d6639e573538dccfCalin Juravle  TestCode(data, true, 1);
641d0d4852847432368b090c184d6639e573538dccfCalin Juravle}
642d0d4852847432368b090c184d6639e573538dccfCalin Juravle
643865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin JuravleTEST(CodegenTest, ReturnDivInt2Addr) {
644865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
645865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::CONST_4 | 4 << 12 | 0,
646865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::CONST_4 | 2 << 12 | 1 << 8,
647865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::DIV_INT_2ADDR | 1 << 12,
648865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle    Instruction::RETURN);
649865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle
650865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle  TestCode(data, true, 2);
651865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle}
652865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle
653d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
654