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