codegen_test.cc revision 5da2180e684ae6afcb55d787f6a69bc97489bb83
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" 23fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell#include "arch/x86/instruction_set_features_x86.h" 245da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray#include "arch/x86/registers_x86.h" 25fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell#include "arch/x86_64/instruction_set_features_x86_64.h" 26927307433af0a9322e8ba77eda37168512a73683Alexandre Rames#include "base/macros.h" 27d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "builder.h" 288a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_arm.h" 295319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "code_generator_arm64.h" 308a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_x86.h" 318a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray#include "code_generator_x86_64.h" 32d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "common_compiler_test.h" 333ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#include "dex_file.h" 34d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "dex_instruction.h" 35cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h" 36d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h" 373ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#include "optimizing_unit_test.h" 38360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "prepare_for_register_allocation.h" 39360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "register_allocator.h" 40360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#include "ssa_liveness_analysis.h" 4155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#include "utils.h" 425da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray#include "utils/arm/managed_register_arm.h" 435da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray#include "utils/x86/managed_register_x86.h" 44d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 45d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "gtest/gtest.h" 46e6362281bb4586f45fd927e9cd1b3b14c6b037edNicolas Geoffray 47d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art { 48d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 49a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// Provide our own codegen, that ensures the C calling conventions 50a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// are preserved. Currently, ART and C do not match as R4 is caller-save 51a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// in ART, and callee-save in C. Alternatively, we could use or write 52a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// the stub that saves and restores all registers, but it is easier 53a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray// to just overwrite the code generator. 54a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffrayclass TestCodeGeneratorARM : public arm::CodeGeneratorARM { 55a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray public: 56a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray TestCodeGeneratorARM(HGraph* graph, 57a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray const ArmInstructionSetFeatures& isa_features, 58a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray const CompilerOptions& compiler_options) 59a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray : arm::CodeGeneratorARM(graph, isa_features, compiler_options) { 605da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray AddAllocatedRegister(Location::RegisterLocation(arm::R6)); 615da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray AddAllocatedRegister(Location::RegisterLocation(arm::R7)); 62a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray } 63a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray 64a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray void SetupBlockedRegisters(bool is_baseline) const OVERRIDE { 65a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray arm::CodeGeneratorARM::SetupBlockedRegisters(is_baseline); 665da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_core_registers_[arm::R4] = true; 675da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_core_registers_[arm::R6] = false; 685da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_core_registers_[arm::R7] = false; 69e6362281bb4586f45fd927e9cd1b3b14c6b037edNicolas Geoffray // Makes pair R6-R7 available. 705da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_register_pairs_[arm::R6_R7] = false; 715da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray } 725da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray}; 735da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 745da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffrayclass TestCodeGeneratorX86 : public x86::CodeGeneratorX86 { 755da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray public: 765da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray TestCodeGeneratorX86(HGraph* graph, 775da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray const X86InstructionSetFeatures& isa_features, 785da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray const CompilerOptions& compiler_options) 795da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray : x86::CodeGeneratorX86(graph, isa_features, compiler_options) { 805da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray // Save edi, we need it for getting enough registers for long multiplication. 815da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray AddAllocatedRegister(Location::RegisterLocation(x86::EDI)); 825da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray } 835da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 845da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray void SetupBlockedRegisters(bool is_baseline) const OVERRIDE { 855da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray x86::CodeGeneratorX86::SetupBlockedRegisters(is_baseline); 865da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray // ebx is a callee-save register in C, but caller-save for ART. 875da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_core_registers_[x86::EBX] = true; 885da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_register_pairs_[x86::EAX_EBX] = true; 895da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_register_pairs_[x86::EDX_EBX] = true; 905da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_register_pairs_[x86::ECX_EBX] = true; 915da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_register_pairs_[x86::EBX_EDI] = true; 925da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 935da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray // Make edi available. 945da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_core_registers_[x86::EDI] = false; 955da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray blocked_register_pairs_[x86::ECX_EDI] = false; 96a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray } 97a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray}; 98a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray 99787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass InternalCodeAllocator : public CodeAllocator { 100d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public: 101d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers InternalCodeAllocator() : size_(0) { } 102d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 103d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray virtual uint8_t* Allocate(size_t size) { 104787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray size_ = size; 105d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray memory_.reset(new uint8_t[size]); 106d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray return memory_.get(); 107d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray } 108d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 109787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray size_t GetSize() const { return size_; } 110787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray uint8_t* GetMemory() const { return memory_.get(); } 111d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 112d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private: 113787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray size_t size_; 114700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<uint8_t[]> memory_; 115d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 116787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator); 117d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 118d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 11955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected> 1208d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffraystatic void Run(const InternalCodeAllocator& allocator, 1218d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray const CodeGenerator& codegen, 1228d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray bool has_result, 12355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain Expected expected) { 12455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain typedef Expected (*fptr)(); 1259cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize()); 12620dfc797dc631bf8d655dcf123f46f13332d3074Dave Allison fptr f = reinterpret_cast<fptr>(allocator.GetMemory()); 1278d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray if (codegen.GetInstructionSet() == kThumb2) { 1288d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray // For thumb we need the bottom bit set. 1298d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1); 1308d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray } 13155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain Expected result = f(); 1329cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray if (has_result) { 1335da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray ASSERT_EQ(expected, result); 1349cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray } 1359cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray} 1369cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray 13755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected> 13855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillainstatic void RunCodeBaseline(HGraph* graph, bool has_result, Expected expected) { 139787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray InternalCodeAllocator allocator; 1409cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray 141cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle CompilerOptions compiler_options; 142fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell std::unique_ptr<const X86InstructionSetFeatures> features_x86( 143fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell X86InstructionSetFeatures::FromCppDefines()); 1445da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray TestCodeGeneratorX86 codegenX86(graph, *features_x86.get(), compiler_options); 14573e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray // We avoid doing a stack overflow check that requires the runtime being setup, 14673e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray // by making sure the compiler knows the methods we are running are leaf methods. 1478a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray codegenX86.CompileBaseline(&allocator, true); 1488a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray if (kRuntimeISA == kX86) { 1498a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray Run(allocator, codegenX86, has_result, expected); 1508a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray } 1519cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray 152579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu std::unique_ptr<const ArmInstructionSetFeatures> features_arm( 153df64950a466c0f00cd36120d1afd389c577cae87Andreas Gampe ArmInstructionSetFeatures::FromCppDefines()); 154579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu TestCodeGeneratorARM codegenARM(graph, *features_arm.get(), compiler_options); 1558a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray codegenARM.CompileBaseline(&allocator, true); 1568a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) { 1578a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray Run(allocator, codegenARM, has_result, expected); 1588a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray } 1599cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray 160fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64( 161fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell X86_64InstructionSetFeatures::FromCppDefines()); 162fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell x86_64::CodeGeneratorX86_64 codegenX86_64(graph, *features_x86_64.get(), compiler_options); 1638a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray codegenX86_64.CompileBaseline(&allocator, true); 1648a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray if (kRuntimeISA == kX86_64) { 1658a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray Run(allocator, codegenX86_64, has_result, expected); 1668a16d97fb8f031822b206e65f9109a071da40563Nicolas Geoffray } 1675319defdf502fc4569316473846b83180ec08035Alexandre Rames 168579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64( 169579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu Arm64InstructionSetFeatures::FromCppDefines()); 170579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu arm64::CodeGeneratorARM64 codegenARM64(graph, *features_arm64.get(), compiler_options); 1715319defdf502fc4569316473846b83180ec08035Alexandre Rames codegenARM64.CompileBaseline(&allocator, true); 1725319defdf502fc4569316473846b83180ec08035Alexandre Rames if (kRuntimeISA == kArm64) { 1735319defdf502fc4569316473846b83180ec08035Alexandre Rames Run(allocator, codegenARM64, has_result, expected); 1745319defdf502fc4569316473846b83180ec08035Alexandre Rames } 175d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} 176d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 17755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected> 178360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void RunCodeOptimized(CodeGenerator* codegen, 179360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HGraph* graph, 180360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray std::function<void(HGraph*)> hook_before_codegen, 181360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray bool has_result, 18255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain Expected expected) { 18310f56cb6b4e39ed0032e9a23b179b557463e65adDavid Brazdil graph->BuildDominatorTree(); 1840d9f17de8f21a10702de1510b73e89d07b3b9bbfNicolas Geoffray SsaLivenessAnalysis liveness(graph, codegen); 185360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray liveness.Analyze(); 186360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 187360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness); 188360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray register_allocator.AllocateRegisters(); 189360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray hook_before_codegen(graph); 190360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 191360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray InternalCodeAllocator allocator; 192360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray codegen->CompileOptimized(&allocator); 193360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray Run(allocator, *codegen, has_result, expected); 194360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray} 195360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 19655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillaintemplate <typename Expected> 197360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void RunCodeOptimized(HGraph* graph, 198360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray std::function<void(HGraph*)> hook_before_codegen, 199360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray bool has_result, 20055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain Expected expected) { 201cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle CompilerOptions compiler_options; 2023e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) { 203a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray TestCodeGeneratorARM codegenARM(graph, 204a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray *ArmInstructionSetFeatures::FromCppDefines(), 205a0bb2bd5b6a049ad806c223f00672d1f0210db67Nicolas Geoffray compiler_options); 206360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray RunCodeOptimized(&codegenARM, graph, hook_before_codegen, has_result, expected); 2073e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames } else if (kRuntimeISA == kArm64) { 208579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu arm64::CodeGeneratorARM64 codegenARM64(graph, 209579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu *Arm64InstructionSetFeatures::FromCppDefines(), 210579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu compiler_options); 2113e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames RunCodeOptimized(&codegenARM64, graph, hook_before_codegen, has_result, expected); 2123e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames } else if (kRuntimeISA == kX86) { 213fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell std::unique_ptr<const X86InstructionSetFeatures> features_x86( 214fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell X86InstructionSetFeatures::FromCppDefines()); 215fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell x86::CodeGeneratorX86 codegenX86(graph, *features_x86.get(), compiler_options); 2163e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames RunCodeOptimized(&codegenX86, graph, hook_before_codegen, has_result, expected); 217360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray } else if (kRuntimeISA == kX86_64) { 218fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64( 219fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell X86_64InstructionSetFeatures::FromCppDefines()); 220fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell x86_64::CodeGeneratorX86_64 codegenX86_64(graph, *features_x86_64.get(), compiler_options); 221360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray RunCodeOptimized(&codegenX86_64, graph, hook_before_codegen, has_result, expected); 222360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray } 223360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray} 224360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 225360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffraystatic void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { 226360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray ArenaPool pool; 227360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray ArenaAllocator arena(&pool); 2285e8b137d28c840b128e2488f954cccee3e86db14David Brazdil HGraph* graph = new (&arena) HGraph(&arena); 2295e8b137d28c840b128e2488f954cccee3e86db14David Brazdil HGraphBuilder builder(graph); 230360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); 2315e8b137d28c840b128e2488f954cccee3e86db14David Brazdil bool graph_built = builder.BuildGraph(*item); 2325e8b137d28c840b128e2488f954cccee3e86db14David Brazdil ASSERT_TRUE(graph_built); 233039b6e2fd3bfadbd1ee8583002f673d6ccba5b7eCalin Juravle // Remove suspend checks, they cannot be executed in this context. 23448dee04f4e4214b0fdd8acd0587ef6b08d3d2456Calin Juravle RemoveSuspendChecks(graph); 235360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray RunCodeBaseline(graph, has_result, expected); 236360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray} 237360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 23855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillainstatic void TestCodeLong(const uint16_t* data, bool has_result, int64_t expected) { 23955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain ArenaPool pool; 24055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain ArenaAllocator arena(&pool); 2415e8b137d28c840b128e2488f954cccee3e86db14David Brazdil HGraph* graph = new (&arena) HGraph(&arena); 2425e8b137d28c840b128e2488f954cccee3e86db14David Brazdil HGraphBuilder builder(graph, Primitive::kPrimLong); 24355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); 2445e8b137d28c840b128e2488f954cccee3e86db14David Brazdil bool graph_built = builder.BuildGraph(*item); 2455e8b137d28c840b128e2488f954cccee3e86db14David Brazdil ASSERT_TRUE(graph_built); 24655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain // Remove suspend checks, they cannot be executed in this context. 24755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain RemoveSuspendChecks(graph); 24855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain RunCodeBaseline(graph, has_result, expected); 24955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain} 25055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain 251d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas GeoffrayTEST(CodegenTest, ReturnVoid) { 2523ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID); 2533ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray TestCode(data); 254d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} 255d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 256bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG1) { 2573ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 258d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::GOTO | 0x100, 2593ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray Instruction::RETURN_VOID); 260d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2613ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray TestCode(data); 262d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} 263d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 264bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG2) { 2653ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 266d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::GOTO | 0x100, 267d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::GOTO | 0x100, 2683ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray Instruction::RETURN_VOID); 269d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2703ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray TestCode(data); 271d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} 272d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 273bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG3) { 2743ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM( 275d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::GOTO | 0x200, 276d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::RETURN_VOID, 2773ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray Instruction::GOTO | 0xFF00); 278d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2793ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray TestCode(data1); 280d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2813ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM( 282d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::GOTO_16, 3, 283d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::RETURN_VOID, 2843ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray Instruction::GOTO_16, 0xFFFF); 285d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2863ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray TestCode(data2); 287d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2883ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM( 289d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::GOTO_32, 4, 0, 290d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::RETURN_VOID, 2913ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray Instruction::GOTO_32, 0xFFFF, 0xFFFF); 292d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2933ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray TestCode(data3); 294d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} 295d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 296bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG4) { 2973ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 298d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::RETURN_VOID, 299d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray Instruction::GOTO | 0x100, 3003ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray Instruction::GOTO | 0xFE00); 301d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 3023ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray TestCode(data); 303d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} 304d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 305bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, CFG5) { 306bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 307bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 0, 308bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::IF_EQ, 3, 309bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::GOTO | 0x100, 310bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN_VOID); 311bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 312bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray TestCode(data); 313bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray} 314bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 315bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, IntConstant) { 316bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 317bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 0, 318bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN_VOID); 319bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 320bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray TestCode(data); 321bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray} 322bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 323bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return1) { 324bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 325bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 0, 326bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN | 0); 327bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 328bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray TestCode(data, true, 0); 329bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray} 330bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 331bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return2) { 332bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 333bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 0, 334bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 1 << 8, 335bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN | 1 << 8); 336bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 337bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray TestCode(data, true, 0); 338bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray} 339bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 340bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, Return3) { 341bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 342bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 0, 343bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 1 << 8 | 1 << 12, 344bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN | 1 << 8); 345bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 346bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray TestCode(data, true, 1); 347bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray} 348bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 349bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, ReturnIf1) { 350bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 351bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 0, 352bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 1 << 8 | 1 << 12, 353bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::IF_EQ, 3, 354bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN | 0 << 8, 355bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN | 1 << 8); 356bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 357bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray TestCode(data, true, 1); 358bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray} 359bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 360bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas GeoffrayTEST(CodegenTest, ReturnIf2) { 361bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 362bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 0 | 0, 363bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::CONST_4 | 1 << 8 | 1 << 12, 364bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::IF_EQ | 0 << 4 | 1 << 8, 3, 365bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN | 0 << 8, 366bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray Instruction::RETURN | 1 << 8); 367bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 368bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray TestCode(data, true, 0); 369bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray} 370bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 3711cc5f251df558b0e22cea5000626365eb644c727Roland Levillain// Exercise bit-wise (one's complement) not-int instruction. 3721cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \ 3731cc5f251df558b0e22cea5000626365eb644c727Roland LevillainTEST(CodegenTest, TEST_NAME) { \ 3741cc5f251df558b0e22cea5000626365eb644c727Roland Levillain const int32_t input = INPUT; \ 37555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const uint16_t input_lo = Low16Bits(input); \ 37655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const uint16_t input_hi = High16Bits(input); \ 3771cc5f251df558b0e22cea5000626365eb644c727Roland Levillain const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( \ 3781cc5f251df558b0e22cea5000626365eb644c727Roland Levillain Instruction::CONST | 0 << 8, input_lo, input_hi, \ 3791cc5f251df558b0e22cea5000626365eb644c727Roland Levillain Instruction::NOT_INT | 1 << 8 | 0 << 12 , \ 3801cc5f251df558b0e22cea5000626365eb644c727Roland Levillain Instruction::RETURN | 1 << 8); \ 3811cc5f251df558b0e22cea5000626365eb644c727Roland Levillain \ 3821cc5f251df558b0e22cea5000626365eb644c727Roland Levillain TestCode(data, true, EXPECTED_OUTPUT); \ 3831cc5f251df558b0e22cea5000626365eb644c727Roland Levillain} 3841cc5f251df558b0e22cea5000626365eb644c727Roland Levillain 3851cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus2, -2, 1) 3861cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotIntMinus1, -1, 0) 3871cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt0, 0, -1) 3881cc5f251df558b0e22cea5000626365eb644c727Roland LevillainNOT_INT_TEST(ReturnNotInt1, 1, -2) 38955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MIN, -2147483648, 2147483647) // (2^31) - 1 39055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MINPlus1, -2147483647, 2147483646) // (2^31) - 2 39155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAXMinus1, 2147483646, -2147483647) // -(2^31) - 1 39255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_INT_TEST(ReturnNotIntINT32_MAX, 2147483647, -2147483648) // -(2^31) 3931cc5f251df558b0e22cea5000626365eb644c727Roland Levillain 3941cc5f251df558b0e22cea5000626365eb644c727Roland Levillain#undef NOT_INT_TEST 3951cc5f251df558b0e22cea5000626365eb644c727Roland Levillain 39655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Exercise bit-wise (one's complement) not-long instruction. 39755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define NOT_LONG_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \ 39855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainTEST(CodegenTest, TEST_NAME) { \ 39955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const int64_t input = INPUT; \ 40055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const uint16_t word0 = Low16Bits(Low32Bits(input)); /* LSW. */ \ 40155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const uint16_t word1 = High16Bits(Low32Bits(input)); \ 40255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const uint16_t word2 = Low16Bits(High32Bits(input)); \ 40355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const uint16_t word3 = High16Bits(High32Bits(input)); /* MSW. */ \ 40455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM( \ 40555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3, \ 40655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain Instruction::NOT_LONG | 2 << 8 | 0 << 12, \ 40755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain Instruction::RETURN_WIDE | 2 << 8); \ 40855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain \ 40955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain TestCodeLong(data, true, EXPECTED_OUTPUT); \ 41055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain} 41155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain 41255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus2, INT64_C(-2), INT64_C(1)) 41355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongMinus1, INT64_C(-1), INT64_C(0)) 41455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong0, INT64_C(0), INT64_C(-1)) 41555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLong1, INT64_C(1), INT64_C(-2)) 41655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain 41755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MIN, 41855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-2147483648), 41955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(2147483647)) // (2^31) - 1 42055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MINPlus1, 42155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-2147483647), 42255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(2147483646)) // (2^31) - 2 42355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAXMinus1, 42455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(2147483646), 42555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-2147483647)) // -(2^31) - 1 42655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT32_MAX, 42755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(2147483647), 42855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-2147483648)) // -(2^31) 42955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain 43055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// Note that the C++ compiler won't accept 43155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// INT64_C(-9223372036854775808) (that is, INT64_MIN) as a valid 43255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain// int64_t literal, so we use INT64_C(-9223372036854775807)-1 instead. 43355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MIN, 43455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-9223372036854775807)-1, 43555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(9223372036854775807)); // (2^63) - 1 43655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotINT64_MINPlus1, 43755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-9223372036854775807), 43855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(9223372036854775806)); // (2^63) - 2 43955dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAXMinus1, 44055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(9223372036854775806), 44155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-9223372036854775807)); // -(2^63) - 1 44255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland LevillainNOT_LONG_TEST(ReturnNotLongINT64_MAX, 44355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(9223372036854775807), 44455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain INT64_C(-9223372036854775807)-1); // -(2^63) 44555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain 44655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#undef NOT_LONG_TEST 44755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain 448946e143941d456a4ec666f7f54719c65c5aa3f5dRoland LevillainTEST(CodegenTest, IntToLongOfLongToInt) { 449946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain const int64_t input = INT64_C(4294967296); // 2^32 450946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain const uint16_t word0 = Low16Bits(Low32Bits(input)); // LSW. 451946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain const uint16_t word1 = High16Bits(Low32Bits(input)); 452946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain const uint16_t word2 = Low16Bits(High32Bits(input)); 453946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain const uint16_t word3 = High16Bits(High32Bits(input)); // MSW. 454946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain const uint16_t data[] = FIVE_REGISTERS_CODE_ITEM( 455946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3, 456946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain Instruction::CONST_WIDE | 2 << 8, 1, 0, 0, 0, 457946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain Instruction::ADD_LONG | 0, 0 << 8 | 2, // v0 <- 2^32 + 1 458946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain Instruction::LONG_TO_INT | 4 << 8 | 0 << 12, 459946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain Instruction::INT_TO_LONG | 2 << 8 | 4 << 12, 460946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain Instruction::RETURN_WIDE | 2 << 8); 461946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain 462946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain TestCodeLong(data, true, 1); 463946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain} 464946e143941d456a4ec666f7f54719c65c5aa3f5dRoland Levillain 465d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd1) { 466d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 467d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::CONST_4 | 3 << 12 | 0, 468d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::CONST_4 | 4 << 12 | 1 << 8, 469d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::ADD_INT, 1 << 8 | 0, 470d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::RETURN); 471d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 472d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray TestCode(data, true, 7); 473d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray} 474d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 475d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd2) { 476d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 477d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::CONST_4 | 3 << 12 | 0, 478d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::CONST_4 | 4 << 12 | 1 << 8, 479d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::ADD_INT_2ADDR | 1 << 12, 480d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::RETURN); 481d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 482d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray TestCode(data, true, 7); 483d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray} 484d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 485d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd3) { 486d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 487d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::CONST_4 | 4 << 12 | 0 << 8, 488d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::ADD_INT_LIT8, 3 << 8 | 0, 489d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::RETURN); 490d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 491d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray TestCode(data, true, 7); 492d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray} 493d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 494d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas GeoffrayTEST(CodegenTest, ReturnAdd4) { 495d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 496d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::CONST_4 | 4 << 12 | 0 << 8, 497d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::ADD_INT_LIT16, 3, 498d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray Instruction::RETURN); 499d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 500d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray TestCode(data, true, 7); 501d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray} 502d8ee737fdbf380c5bb90c9270c8d1087ac23e76cNicolas Geoffray 503360231a056e796c36ffe62348507e904dc9efb9bNicolas GeoffrayTEST(CodegenTest, NonMaterializedCondition) { 504360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray ArenaPool pool; 505360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray ArenaAllocator allocator(&pool); 506360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 507360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HGraph* graph = new (&allocator) HGraph(&allocator); 508360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HBasicBlock* entry = new (&allocator) HBasicBlock(graph); 509360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray graph->AddBlock(entry); 510360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray graph->SetEntryBlock(entry); 511360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray entry->AddInstruction(new (&allocator) HGoto()); 512360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 513360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HBasicBlock* first_block = new (&allocator) HBasicBlock(graph); 514360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray graph->AddBlock(first_block); 515360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray entry->AddSuccessor(first_block); 5168d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* constant0 = graph->GetIntConstant(0); 5178d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* constant1 = graph->GetIntConstant(1); 518360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HEqual* equal = new (&allocator) HEqual(constant0, constant0); 519360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray first_block->AddInstruction(equal); 520360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray first_block->AddInstruction(new (&allocator) HIf(equal)); 521360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 522360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HBasicBlock* then = new (&allocator) HBasicBlock(graph); 523360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HBasicBlock* else_ = new (&allocator) HBasicBlock(graph); 524360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray HBasicBlock* exit = new (&allocator) HBasicBlock(graph); 525360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 526360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray graph->AddBlock(then); 527360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray graph->AddBlock(else_); 528360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray graph->AddBlock(exit); 529360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray first_block->AddSuccessor(then); 530360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray first_block->AddSuccessor(else_); 531360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray then->AddSuccessor(exit); 532360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray else_->AddSuccessor(exit); 533360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 534360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray exit->AddInstruction(new (&allocator) HExit()); 535360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray then->AddInstruction(new (&allocator) HReturn(constant0)); 536360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray else_->AddInstruction(new (&allocator) HReturn(constant1)); 537360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 538360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray ASSERT_TRUE(equal->NeedsMaterialization()); 539360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray graph->BuildDominatorTree(); 540360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray PrepareForRegisterAllocation(graph).Run(); 541360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray ASSERT_FALSE(equal->NeedsMaterialization()); 542360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 543277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe auto hook_before_codegen = [](HGraph* graph_in) { 544277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0); 545277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena()); 546360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray block->InsertInstructionBefore(move, block->GetLastInstruction()); 547360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray }; 548360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 549360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray RunCodeOptimized(graph, hook_before_codegen, true, 0); 550360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray} 551360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray 5525da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas GeoffrayTEST(CodegenTest, ReturnMulInt) { 5535da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 5545da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 3 << 12 | 0, 5555da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 4 << 12 | 1 << 8, 5565da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::MUL_INT, 1 << 8 | 0, 5575da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::RETURN); 5585da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 5595da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray TestCode(data, true, 12); 5605da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray} 5615da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 5625da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas GeoffrayTEST(CodegenTest, ReturnMulInt2addr) { 5635da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 5645da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 3 << 12 | 0, 5655da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 4 << 12 | 1 << 8, 5665da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::MUL_INT_2ADDR | 1 << 12, 5675da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::RETURN); 56834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 5695da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray TestCode(data, true, 12); 5705da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray} 5715da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 5725da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas GeoffrayTEST(CodegenTest, ReturnMulLong) { 5735da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM( 5745da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 3 << 12 | 0, 5755da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 0 << 12 | 1 << 8, 5765da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 4 << 12 | 2 << 8, 5775da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 0 << 12 | 3 << 8, 5785da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::MUL_LONG, 2 << 8 | 0, 5795da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::RETURN_WIDE); 5805da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 5815da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray TestCodeLong(data, true, 12); 5825da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray} 5835da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 5845da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas GeoffrayTEST(CodegenTest, ReturnMulLong2addr) { 5855da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM( 5865da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 3 << 12 | 0 << 8, 5875da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 0 << 12 | 1 << 8, 5885da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 4 << 12 | 2 << 8, 5895da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::CONST_4 | 0 << 12 | 3 << 8, 5905da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::MUL_LONG_2ADDR | 2 << 12, 5915da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray Instruction::RETURN_WIDE); 5925da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray 5935da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray TestCodeLong(data, true, 12); 5945da2180e684ae6afcb55d787f6a69bc97489bb83Nicolas Geoffray} 59534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 59634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleTEST(CodegenTest, ReturnMulIntLit8) { 59734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 59834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle Instruction::CONST_4 | 4 << 12 | 0 << 8, 59934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle Instruction::MUL_INT_LIT8, 3 << 8 | 0, 60034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle Instruction::RETURN); 60134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 60234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle TestCode(data, true, 12); 60334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle} 60434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 60534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin JuravleTEST(CodegenTest, ReturnMulIntLit16) { 60634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 60734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle Instruction::CONST_4 | 4 << 12 | 0 << 8, 60834bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle Instruction::MUL_INT_LIT16, 3, 60934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle Instruction::RETURN); 61034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 61134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle TestCode(data, true, 12); 61234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle} 61334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 614927307433af0a9322e8ba77eda37168512a73683Alexandre RamesTEST(CodegenTest, MaterializedCondition1) { 615927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // Check that condition are materialized correctly. A materialized condition 616927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // should yield `1` if it evaluated to true, and `0` otherwise. 617927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // We force the materialization of comparisons for different combinations of 618927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // inputs and check the results. 619927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 620927307433af0a9322e8ba77eda37168512a73683Alexandre Rames int lhs[] = {1, 2, -1, 2, 0xabc}; 621927307433af0a9322e8ba77eda37168512a73683Alexandre Rames int rhs[] = {2, 1, 2, -1, 0xabc}; 622927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 623927307433af0a9322e8ba77eda37168512a73683Alexandre Rames for (size_t i = 0; i < arraysize(lhs); i++) { 624927307433af0a9322e8ba77eda37168512a73683Alexandre Rames ArenaPool pool; 625927307433af0a9322e8ba77eda37168512a73683Alexandre Rames ArenaAllocator allocator(&pool); 626927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HGraph* graph = new (&allocator) HGraph(&allocator); 627927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 628927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph); 629927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(entry_block); 630927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->SetEntryBlock(entry_block); 631927307433af0a9322e8ba77eda37168512a73683Alexandre Rames entry_block->AddInstruction(new (&allocator) HGoto()); 632927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* code_block = new (&allocator) HBasicBlock(graph); 633927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(code_block); 634927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph); 635927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(exit_block); 636927307433af0a9322e8ba77eda37168512a73683Alexandre Rames exit_block->AddInstruction(new (&allocator) HExit()); 637927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 638927307433af0a9322e8ba77eda37168512a73683Alexandre Rames entry_block->AddSuccessor(code_block); 639927307433af0a9322e8ba77eda37168512a73683Alexandre Rames code_block->AddSuccessor(exit_block); 640927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->SetExitBlock(exit_block); 641927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 6428d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]); 6438d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]); 6448d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HLessThan cmp_lt(cst_lhs, cst_rhs); 645927307433af0a9322e8ba77eda37168512a73683Alexandre Rames code_block->AddInstruction(&cmp_lt); 646927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HReturn ret(&cmp_lt); 647927307433af0a9322e8ba77eda37168512a73683Alexandre Rames code_block->AddInstruction(&ret); 648927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 649277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe auto hook_before_codegen = [](HGraph* graph_in) { 650277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0); 651277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena()); 652927307433af0a9322e8ba77eda37168512a73683Alexandre Rames block->InsertInstructionBefore(move, block->GetLastInstruction()); 653927307433af0a9322e8ba77eda37168512a73683Alexandre Rames }; 654927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 655927307433af0a9322e8ba77eda37168512a73683Alexandre Rames RunCodeOptimized(graph, hook_before_codegen, true, lhs[i] < rhs[i]); 656927307433af0a9322e8ba77eda37168512a73683Alexandre Rames } 657927307433af0a9322e8ba77eda37168512a73683Alexandre Rames} 658927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 659927307433af0a9322e8ba77eda37168512a73683Alexandre RamesTEST(CodegenTest, MaterializedCondition2) { 660927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // Check that HIf correctly interprets a materialized condition. 661927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // We force the materialization of comparisons for different combinations of 662927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // inputs. An HIf takes the materialized combination as input and returns a 663927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // value that we verify. 664927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 665927307433af0a9322e8ba77eda37168512a73683Alexandre Rames int lhs[] = {1, 2, -1, 2, 0xabc}; 666927307433af0a9322e8ba77eda37168512a73683Alexandre Rames int rhs[] = {2, 1, 2, -1, 0xabc}; 667927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 668927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 669927307433af0a9322e8ba77eda37168512a73683Alexandre Rames for (size_t i = 0; i < arraysize(lhs); i++) { 670927307433af0a9322e8ba77eda37168512a73683Alexandre Rames ArenaPool pool; 671927307433af0a9322e8ba77eda37168512a73683Alexandre Rames ArenaAllocator allocator(&pool); 672927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HGraph* graph = new (&allocator) HGraph(&allocator); 673927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 674927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph); 675927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(entry_block); 676927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->SetEntryBlock(entry_block); 677927307433af0a9322e8ba77eda37168512a73683Alexandre Rames entry_block->AddInstruction(new (&allocator) HGoto()); 678927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 679927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* if_block = new (&allocator) HBasicBlock(graph); 680927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(if_block); 681927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* if_true_block = new (&allocator) HBasicBlock(graph); 682927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(if_true_block); 683927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* if_false_block = new (&allocator) HBasicBlock(graph); 684927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(if_false_block); 685927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph); 686927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->AddBlock(exit_block); 687927307433af0a9322e8ba77eda37168512a73683Alexandre Rames exit_block->AddInstruction(new (&allocator) HExit()); 688927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 689927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->SetEntryBlock(entry_block); 690927307433af0a9322e8ba77eda37168512a73683Alexandre Rames entry_block->AddSuccessor(if_block); 691927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_block->AddSuccessor(if_true_block); 692927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_block->AddSuccessor(if_false_block); 693927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_true_block->AddSuccessor(exit_block); 694927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_false_block->AddSuccessor(exit_block); 695927307433af0a9322e8ba77eda37168512a73683Alexandre Rames graph->SetExitBlock(exit_block); 696927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 6978d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]); 6988d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]); 6998d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HLessThan cmp_lt(cst_lhs, cst_rhs); 700927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_block->AddInstruction(&cmp_lt); 701927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // We insert a temporary to separate the HIf from the HLessThan and force 702927307433af0a9322e8ba77eda37168512a73683Alexandre Rames // the materialization of the condition. 703927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HTemporary force_materialization(0); 704927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_block->AddInstruction(&force_materialization); 705927307433af0a9322e8ba77eda37168512a73683Alexandre Rames HIf if_lt(&cmp_lt); 706927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_block->AddInstruction(&if_lt); 707927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 7088d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* cst_lt = graph->GetIntConstant(1); 7098d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HReturn ret_lt(cst_lt); 710927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_true_block->AddInstruction(&ret_lt); 7118d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* cst_ge = graph->GetIntConstant(0); 7128d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HReturn ret_ge(cst_ge); 713927307433af0a9322e8ba77eda37168512a73683Alexandre Rames if_false_block->AddInstruction(&ret_ge); 714927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 715277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe auto hook_before_codegen = [](HGraph* graph_in) { 716277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0); 717277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena()); 718927307433af0a9322e8ba77eda37168512a73683Alexandre Rames block->InsertInstructionBefore(move, block->GetLastInstruction()); 719927307433af0a9322e8ba77eda37168512a73683Alexandre Rames }; 720927307433af0a9322e8ba77eda37168512a73683Alexandre Rames 721927307433af0a9322e8ba77eda37168512a73683Alexandre Rames RunCodeOptimized(graph, hook_before_codegen, true, lhs[i] < rhs[i]); 722927307433af0a9322e8ba77eda37168512a73683Alexandre Rames } 723927307433af0a9322e8ba77eda37168512a73683Alexandre Rames} 72434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 725d0d4852847432368b090c184d6639e573538dccfCalin JuravleTEST(CodegenTest, ReturnDivIntLit8) { 726d0d4852847432368b090c184d6639e573538dccfCalin Juravle const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 727d0d4852847432368b090c184d6639e573538dccfCalin Juravle Instruction::CONST_4 | 4 << 12 | 0 << 8, 728d0d4852847432368b090c184d6639e573538dccfCalin Juravle Instruction::DIV_INT_LIT8, 3 << 8 | 0, 729d0d4852847432368b090c184d6639e573538dccfCalin Juravle Instruction::RETURN); 730d0d4852847432368b090c184d6639e573538dccfCalin Juravle 731d0d4852847432368b090c184d6639e573538dccfCalin Juravle TestCode(data, true, 1); 732d0d4852847432368b090c184d6639e573538dccfCalin Juravle} 733d0d4852847432368b090c184d6639e573538dccfCalin Juravle 734865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin JuravleTEST(CodegenTest, ReturnDivInt2Addr) { 735865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 736865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle Instruction::CONST_4 | 4 << 12 | 0, 737865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle Instruction::CONST_4 | 2 << 12 | 1 << 8, 738865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle Instruction::DIV_INT_2ADDR | 1 << 12, 739865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle Instruction::RETURN); 740865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle 741865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle TestCode(data, true, 2); 742865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle} 743865fc88fdfd006ce0362c2c0d55c66a7bffdab61Calin Juravle 744d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace art 745