13ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray/* 23ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project 33ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * 43ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 53ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * you may not use this file except in compliance with the License. 63ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * You may obtain a copy of the License at 73ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * 83ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 93ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * 103ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software 113ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 123ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * See the License for the specific language governing permissions and 143ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray * limitations under the License. 153ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray */ 163ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray 173ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#ifndef ART_COMPILER_OPTIMIZING_OPTIMIZING_UNIT_TEST_H_ 183ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#define ART_COMPILER_OPTIMIZING_OPTIMIZING_UNIT_TEST_H_ 193ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray 20ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain#include "nodes.h" 21ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain#include "builder.h" 224833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil#include "common_compiler_test.h" 23ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain#include "dex_file.h" 24ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain#include "dex_instruction.h" 254833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil#include "handle_scope-inl.h" 264833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil#include "scoped_thread_state_change.h" 274833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil#include "ssa_builder.h" 28a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "ssa_liveness_analysis.h" 29a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 3072bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain#include "gtest/gtest.h" 3172bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain 32a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraynamespace art { 33a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 343ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#define NUM_INSTRUCTIONS(...) \ 353ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray (sizeof((uint16_t[]) {__VA_ARGS__}) /sizeof(uint16_t)) 363ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray 3755dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define N_REGISTERS_CODE_ITEM(NUM_REGS, ...) \ 3855dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain { NUM_REGS, 0, 0, 0, 0, 0, NUM_INSTRUCTIONS(__VA_ARGS__), 0, __VA_ARGS__ } 393ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray 4055dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define ZERO_REGISTER_CODE_ITEM(...) N_REGISTERS_CODE_ITEM(0, __VA_ARGS__) 4155dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define ONE_REGISTER_CODE_ITEM(...) N_REGISTERS_CODE_ITEM(1, __VA_ARGS__) 4255dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define TWO_REGISTERS_CODE_ITEM(...) N_REGISTERS_CODE_ITEM(2, __VA_ARGS__) 4355dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define THREE_REGISTERS_CODE_ITEM(...) N_REGISTERS_CODE_ITEM(3, __VA_ARGS__) 4455dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define FOUR_REGISTERS_CODE_ITEM(...) N_REGISTERS_CODE_ITEM(4, __VA_ARGS__) 4555dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define FIVE_REGISTERS_CODE_ITEM(...) N_REGISTERS_CODE_ITEM(5, __VA_ARGS__) 4655dcfb5e0dd626993bb2b7b9f692c1b02b5d955fRoland Levillain#define SIX_REGISTERS_CODE_ITEM(...) N_REGISTERS_CODE_ITEM(6, __VA_ARGS__) 473ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray 48a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas GeoffrayLiveInterval* BuildInterval(const size_t ranges[][2], 49a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray size_t number_of_ranges, 50a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray ArenaAllocator* allocator, 51dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray int reg = -1, 52dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray HInstruction* defined_by = nullptr) { 53dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray LiveInterval* interval = LiveInterval::MakeInterval(allocator, Primitive::kPrimInt, defined_by); 54dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray if (defined_by != nullptr) { 55dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray defined_by->SetLiveInterval(interval); 56dd8f887e81b894bc8075d8bacdb223747b6a8018Nicolas Geoffray } 57a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray for (size_t i = number_of_ranges; i > 0; --i) { 58a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray interval->AddRange(ranges[i - 1][0], ranges[i - 1][1]); 59a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray } 60a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray interval->SetRegister(reg); 61a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray return interval; 62a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} 63a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 64fbc695f9b8e2084697e19c1355ab925f99f0d235Nicolas Geoffrayvoid RemoveSuspendChecks(HGraph* graph) { 65fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko for (HBasicBlock* block : graph->GetBlocks()) { 66badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil if (block != nullptr) { 67badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) { 68badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil HInstruction* current = it.Current(); 69badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil if (current->IsSuspendCheck()) { 70badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil current->GetBlock()->RemoveInstruction(current); 71badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil } 72fbc695f9b8e2084697e19c1355ab925f99f0d235Nicolas Geoffray } 73fbc695f9b8e2084697e19c1355ab925f99f0d235Nicolas Geoffray } 74fbc695f9b8e2084697e19c1355ab925f99f0d235Nicolas Geoffray } 75fbc695f9b8e2084697e19c1355ab925f99f0d235Nicolas Geoffray} 76fbc695f9b8e2084697e19c1355ab925f99f0d235Nicolas Geoffray 770a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffrayinline HGraph* CreateGraph(ArenaAllocator* allocator) { 780a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray return new (allocator) HGraph( 79e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier allocator, *reinterpret_cast<DexFile*>(allocator->Alloc(sizeof(DexFile))), -1, false, 80e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kRuntimeISA); 810a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray} 820a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray 83ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain// Create a control-flow graph from Dex instructions. 847fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffrayinline HGraph* CreateCFG(ArenaAllocator* allocator, 857fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const uint16_t* data, 867fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray Primitive::Type return_type = Primitive::kPrimInt) { 87ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain const DexFile::CodeItem* item = 88ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain reinterpret_cast<const DexFile::CodeItem*>(data); 89badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil HGraph* graph = CreateGraph(allocator); 90badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil 91badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil { 92badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil ScopedObjectAccess soa(Thread::Current()); 93badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil StackHandleScopeCollection handles(soa.Self()); 94dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil HGraphBuilder builder(graph, *item, &handles, return_type); 95dee58d6bb6d567fcd0c4f39d8d690c3acaf0e432David Brazdil bool graph_built = (builder.BuildGraph() == kAnalysisSuccess); 96badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil return graph_built ? graph : nullptr; 97badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil } 98ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain} 99ccc07a9579c554443cd03a306ca9b4f943fd2a93Roland Levillain 10072bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain// Naive string diff data type. 10172bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillaintypedef std::list<std::pair<std::string, std::string>> diff_t; 10272bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain 10372bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain// An alias for the empty string used to make it clear that a line is 10472bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain// removed in a diff. 10572bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillainstatic const std::string removed = ""; 10672bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain 10772bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain// Naive patch command: apply a diff to a string. 10872bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillaininline std::string Patch(const std::string& original, const diff_t& diff) { 10972bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain std::string result = original; 11072bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain for (const auto& p : diff) { 11172bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain std::string::size_type pos = result.find(p.first); 11286ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil DCHECK_NE(pos, std::string::npos) 11386ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil << "Could not find: \"" << p.first << "\" in \"" << result << "\""; 11472bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain result.replace(pos, p.first.size(), p.second); 11572bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain } 11672bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain return result; 11772bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain} 11872bceff11a98cc1ecdb64a6fae16c521f99ec6a7Roland Levillain 119f384f88d4d1e89df82f47fbc7245a8acc9c2d49cMingyao Yang// Returns if the instruction is removed from the graph. 120f384f88d4d1e89df82f47fbc7245a8acc9c2d49cMingyao Yanginline bool IsRemoved(HInstruction* instruction) { 121f384f88d4d1e89df82f47fbc7245a8acc9c2d49cMingyao Yang return instruction->GetBlock() == nullptr; 122f384f88d4d1e89df82f47fbc7245a8acc9c2d49cMingyao Yang} 123f384f88d4d1e89df82f47fbc7245a8acc9c2d49cMingyao Yang 124a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray} // namespace art 125a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 1263ff386aafefd5282bb76c8a50506a70a4321e698Nicolas Geoffray#endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_UNIT_TEST_H_ 127