diff options
| -rw-r--r-- | compiler/Android.bp | 1 | ||||
| -rw-r--r-- | compiler/jit/jit_compiler.cc | 7 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips.cc | 51 | ||||
| -rw-r--r-- | compiler/optimizing/load_store_elimination.cc | 75 | ||||
| -rw-r--r-- | compiler/optimizing/load_store_elimination_test.cc | 406 | ||||
| -rw-r--r-- | test/165-lock-owner-proxy/src/Main.java | 16 | ||||
| -rw-r--r-- | test/913-heaps/build | 20 | ||||
| -rw-r--r-- | test/913-heaps/check | 5 | ||||
| -rw-r--r-- | test/913-heaps/expected_d8.diff | 76 |
9 files changed, 146 insertions, 511 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp index 1a2d9aa5e6..859947108e 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -355,7 +355,6 @@ art_cc_test { "jni/jni_cfi_test.cc", "optimizing/codegen_test.cc", "optimizing/load_store_analysis_test.cc", - "optimizing/load_store_elimination_test.cc", "optimizing/optimizing_cfi_test.cc", "optimizing/scheduler_test.cc", ], diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index 5c89869e00..0c82d601a7 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -80,6 +80,9 @@ extern "C" void jit_types_loaded(void* handle, mirror::Class** types, size_t cou JitCompiler::JitCompiler() { compiler_options_.reset(new CompilerOptions()); + // Special case max code units for inlining, whose default is "unset" (implictly + // meaning no limit). Do this before parsing the actuall passed options. + compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits); { std::string error_msg; if (!compiler_options_->ParseCompilerOptions(Runtime::Current()->GetCompilerOptions(), @@ -95,10 +98,6 @@ JitCompiler::JitCompiler() { // Set debuggability based on the runtime value. compiler_options_->SetDebuggable(Runtime::Current()->IsJavaDebuggable()); - // Special case max code units for inlining, whose default is "unset" (implictly - // meaning no limit). - compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits); - const InstructionSet instruction_set = kRuntimeISA; for (const StringPiece option : Runtime::Current()->GetCompilerOptions()) { VLOG(compiler) << "JIT compiler option " << option; diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index f9f5a4da56..ddec0cc453 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -2474,6 +2474,7 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) { } } } else { + const bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); MipsLabel done; if (instr->IsShl()) { __ Sllv(dst_low, lhs_low, rhs_reg); @@ -2483,9 +2484,14 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) { __ Sllv(dst_high, lhs_high, rhs_reg); __ Or(dst_high, dst_high, TMP); __ Andi(TMP, rhs_reg, kMipsBitsPerWord); - __ Beqz(TMP, &done); - __ Move(dst_high, dst_low); - __ Move(dst_low, ZERO); + if (isR6) { + __ Beqzc(TMP, &done, /* is_bare */ true); + __ Move(dst_high, dst_low); + __ Move(dst_low, ZERO); + } else { + __ Movn(dst_high, dst_low, TMP); + __ Movn(dst_low, ZERO, TMP); + } } else if (instr->IsShr()) { __ Srav(dst_high, lhs_high, rhs_reg); __ Nor(AT, ZERO, rhs_reg); @@ -2494,9 +2500,15 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) { __ Srlv(dst_low, lhs_low, rhs_reg); __ Or(dst_low, dst_low, TMP); __ Andi(TMP, rhs_reg, kMipsBitsPerWord); - __ Beqz(TMP, &done); - __ Move(dst_low, dst_high); - __ Sra(dst_high, dst_high, 31); + if (isR6) { + __ Beqzc(TMP, &done, /* is_bare */ true); + __ Move(dst_low, dst_high); + __ Sra(dst_high, dst_high, 31); + } else { + __ Sra(AT, dst_high, 31); + __ Movn(dst_low, dst_high, TMP); + __ Movn(dst_high, AT, TMP); + } } else if (instr->IsUShr()) { __ Srlv(dst_high, lhs_high, rhs_reg); __ Nor(AT, ZERO, rhs_reg); @@ -2505,10 +2517,15 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) { __ Srlv(dst_low, lhs_low, rhs_reg); __ Or(dst_low, dst_low, TMP); __ Andi(TMP, rhs_reg, kMipsBitsPerWord); - __ Beqz(TMP, &done); - __ Move(dst_low, dst_high); - __ Move(dst_high, ZERO); - } else { + if (isR6) { + __ Beqzc(TMP, &done, /* is_bare */ true); + __ Move(dst_low, dst_high); + __ Move(dst_high, ZERO); + } else { + __ Movn(dst_low, dst_high, TMP); + __ Movn(dst_high, ZERO, TMP); + } + } else { // Rotate. __ Nor(AT, ZERO, rhs_reg); __ Srlv(TMP, lhs_low, rhs_reg); __ Sll(dst_low, lhs_high, 1); @@ -2519,10 +2536,16 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) { __ Sllv(dst_high, dst_high, AT); __ Or(dst_high, dst_high, TMP); __ Andi(TMP, rhs_reg, kMipsBitsPerWord); - __ Beqz(TMP, &done); - __ Move(TMP, dst_high); - __ Move(dst_high, dst_low); - __ Move(dst_low, TMP); + if (isR6) { + __ Beqzc(TMP, &done, /* is_bare */ true); + __ Move(TMP, dst_high); + __ Move(dst_high, dst_low); + __ Move(dst_low, TMP); + } else { + __ Movn(AT, dst_high, TMP); + __ Movn(dst_high, dst_low, TMP); + __ Movn(dst_low, AT, TMP); + } } __ Bind(&done); } diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index 7d953c0963..605fdae0f8 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -83,8 +83,7 @@ class LSEVisitor : public HGraphDelegateVisitor { DCHECK(load != nullptr); DCHECK(load->IsInstanceFieldGet() || load->IsStaticFieldGet() || - load->IsArrayGet() || - load->IsVecLoad()); + load->IsArrayGet()); HInstruction* substitute = substitute_instructions_for_loads_[i]; DCHECK(substitute != nullptr); // Keep tracing substitute till one that's not removed. @@ -99,10 +98,7 @@ class LSEVisitor : public HGraphDelegateVisitor { // At this point, stores in possibly_removed_stores_ can be safely removed. for (HInstruction* store : possibly_removed_stores_) { - DCHECK(store->IsInstanceFieldSet() || - store->IsStaticFieldSet() || - store->IsArraySet() || - store->IsVecStore()); + DCHECK(store->IsInstanceFieldSet() || store->IsStaticFieldSet() || store->IsArraySet()); store->GetBlock()->RemoveInstruction(store); } @@ -141,9 +137,7 @@ class LSEVisitor : public HGraphDelegateVisitor { void KeepIfIsStore(HInstruction* heap_value) { if (heap_value == kDefaultHeapValue || heap_value == kUnknownHeapValue || - !(heap_value->IsInstanceFieldSet() || - heap_value->IsArraySet() || - heap_value->IsVecStore())) { + !(heap_value->IsInstanceFieldSet() || heap_value->IsArraySet())) { return; } auto idx = std::find(possibly_removed_stores_.begin(), @@ -326,9 +320,7 @@ class LSEVisitor : public HGraphDelegateVisitor { return; } if (heap_value != kUnknownHeapValue) { - if (heap_value->IsInstanceFieldSet() || - heap_value->IsArraySet() || - heap_value->IsVecStore()) { + if (heap_value->IsInstanceFieldSet() || heap_value->IsArraySet()) { HInstruction* store = heap_value; // This load must be from a singleton since it's from the same // field/element that a "removed" store puts the value. That store @@ -426,9 +418,7 @@ class LSEVisitor : public HGraphDelegateVisitor { if (!same_value) { if (possibly_redundant) { - DCHECK(instruction->IsInstanceFieldSet() || - instruction->IsArraySet() || - instruction->IsVecStore()); + DCHECK(instruction->IsInstanceFieldSet() || instruction->IsArraySet()); // Put the store as the heap value. If the value is loaded from heap // by a load later, this store isn't really redundant. heap_values[idx] = instruction; @@ -441,24 +431,8 @@ class LSEVisitor : public HGraphDelegateVisitor { if (i == idx) { continue; } - if (heap_values[i] == value && !instruction->IsVecOperation()) { - // For field/array, same value should be kept even if aliasing happens. - // - // For vector values , this is NOT safe. For example: - // packed_data = [0xA, 0xB, 0xC, 0xD]; <-- Different values in each lane. - // VecStore array[i ,i+1,i+2,i+3] = packed_data; - // VecStore array[i+1,i+2,i+3,i+4] = packed_data; <-- We are here (partial overlap). - // VecLoad vx = array[i,i+1,i+2,i+3]; <-- Cannot be eliminated. - // - // TODO: to allow such 'same value' optimization on vector data, - // LSA needs to report more fine-grain MAY alias information: - // (1) May alias due to two vector data partial overlap. - // e.g. a[i..i+3] and a[i+1,..,i+4]. - // (2) May alias due to two vector data may complete overlap each other. - // e.g. a[i..i+3] and b[i..i+3]. - // (3) May alias but the exact relationship between two locations is unknown. - // e.g. a[i..i+3] and b[j..j+3], where values of a,b,i,j are all unknown. - // This 'same value' optimization can apply only on case (2). + if (heap_values[i] == value) { + // Same value should be kept even if aliasing happens. continue; } if (heap_values[i] == kUnknownHeapValue) { @@ -548,32 +522,6 @@ class LSEVisitor : public HGraphDelegateVisitor { value); } - void VisitVecLoad(HVecLoad* instruction) OVERRIDE { - HInstruction* array = instruction->InputAt(0); - HInstruction* index = instruction->InputAt(1); - size_t vector_length = instruction->GetVectorLength(); - VisitGetLocation(instruction, - array, - HeapLocation::kInvalidFieldOffset, - index, - vector_length, - HeapLocation::kDeclaringClassDefIndexForArrays); - } - - void VisitVecStore(HVecStore* instruction) OVERRIDE { - HInstruction* array = instruction->InputAt(0); - HInstruction* index = instruction->InputAt(1); - HInstruction* value = instruction->InputAt(2); - size_t vector_length = instruction->GetVectorLength(); - VisitSetLocation(instruction, - array, - HeapLocation::kInvalidFieldOffset, - index, - vector_length, - HeapLocation::kDeclaringClassDefIndexForArrays, - value); - } - void VisitDeoptimize(HDeoptimize* instruction) { const ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[instruction->GetBlock()->GetBlockId()]; @@ -583,9 +531,7 @@ class LSEVisitor : public HGraphDelegateVisitor { continue; } // A store is kept as the heap value for possibly removed stores. - if (heap_value->IsInstanceFieldSet() || - heap_value->IsArraySet() || - heap_value->IsVecStore()) { + if (heap_value->IsInstanceFieldSet() || heap_value->IsArraySet()) { // Check whether the reference for a store is used by an environment local of // HDeoptimize. HInstruction* reference = heap_value->InputAt(0); @@ -743,6 +689,11 @@ void LoadStoreElimination::Run() { return; } + // TODO: analyze VecLoad/VecStore better. + if (graph_->HasSIMD()) { + return; + } + LSEVisitor lse_visitor(graph_, heap_location_collector, side_effects_, stats_); for (HBasicBlock* block : graph_->GetReversePostOrder()) { lse_visitor.VisitBasicBlock(block); diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc deleted file mode 100644 index 6f42d96154..0000000000 --- a/compiler/optimizing/load_store_elimination_test.cc +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "side_effects_analysis.h" -#include "load_store_analysis.h" -#include "load_store_elimination.h" -#include "nodes.h" -#include "optimizing_unit_test.h" - -#include "gtest/gtest.h" - -namespace art { - -class LoadStoreEliminationTest : public OptimizingUnitTest { - public: - LoadStoreEliminationTest() : pool_() {} - - void PerformLSE() { - graph_->BuildDominatorTree(); - SideEffectsAnalysis side_effects(graph_); - side_effects.Run(); - LoadStoreAnalysis lsa(graph_); - lsa.Run(); - LoadStoreElimination lse(graph_, side_effects, lsa, nullptr); - lse.Run(); - } - - void CreateTestControlFlowGraph() { - graph_ = CreateGraph(); - - entry_ = new (GetAllocator()) HBasicBlock(graph_); - pre_header_ = new (GetAllocator()) HBasicBlock(graph_); - loop_header_ = new (GetAllocator()) HBasicBlock(graph_); - loop_body_ = new (GetAllocator()) HBasicBlock(graph_); - exit_ = new (GetAllocator()) HBasicBlock(graph_); - - graph_->AddBlock(entry_); - graph_->AddBlock(pre_header_); - graph_->AddBlock(loop_header_); - graph_->AddBlock(loop_body_); - graph_->AddBlock(exit_); - - graph_->SetEntryBlock(entry_); - - // This common CFG has been used by all cases in this load_store_elimination_test. - // entry - // | - // pre_header - // | - // loop_header <--+ - // | | - // loop_body -----+ - // | - // exit - - entry_->AddSuccessor(pre_header_); - pre_header_->AddSuccessor(loop_header_); - loop_header_->AddSuccessor(exit_); // true successor - loop_header_->AddSuccessor(loop_body_); // false successor - loop_body_->AddSuccessor(loop_header_); - - HInstruction* c0 = graph_->GetIntConstant(0); - HInstruction* c1 = graph_->GetIntConstant(1); - HInstruction* c4 = graph_->GetIntConstant(4); - HInstruction* c128 = graph_->GetIntConstant(128); - - // entry block has following instructions: - // array, i, j, i+1, i+4. - array_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(), - dex::TypeIndex(0), - 0, - DataType::Type::kReference); - i_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(), - dex::TypeIndex(1), - 1, - DataType::Type::kInt32); - j_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(), - dex::TypeIndex(1), - 2, - DataType::Type::kInt32); - i_add1_ = new (GetAllocator()) HAdd(DataType::Type::kInt32, i_, c1); - i_add4_ = new (GetAllocator()) HAdd(DataType::Type::kInt32, i_, c4); - entry_->AddInstruction(array_); - entry_->AddInstruction(i_); - entry_->AddInstruction(j_); - entry_->AddInstruction(i_add1_); - entry_->AddInstruction(i_add4_); - entry_->AddInstruction(new (GetAllocator()) HGoto()); - - // pre_header block - pre_header_->AddInstruction(new (GetAllocator()) HGoto()); - - // loop header block has following instructions: - // phi = 0; - // if (phi >= 128); - phi_ = new (GetAllocator()) HPhi(GetAllocator(), 0, 0, DataType::Type::kInt32); - cmp_ = new (GetAllocator()) HGreaterThanOrEqual(phi_, c128); - if_ = new (GetAllocator()) HIf(cmp_); - loop_header_->AddPhi(phi_); - loop_header_->AddInstruction(cmp_); - loop_header_->AddInstruction(if_); - phi_->AddInput(c0); - - // loop body block has following instructions: - // phi++; - HInstruction* inc_phi = new (GetAllocator()) HAdd(DataType::Type::kInt32, phi_, c1); - loop_body_->AddInstruction(inc_phi); - loop_body_->AddInstruction(new (GetAllocator()) HGoto()); - phi_->AddInput(inc_phi); - - // exit block - exit_->AddInstruction(new (GetAllocator()) HExit()); - } - - // To avoid tedious HIR assembly in test functions. - HInstruction* AddVecLoad(HBasicBlock* block, HInstruction* array, HInstruction* index) { - DCHECK(block != nullptr); - DCHECK(array != nullptr); - DCHECK(index != nullptr); - HInstruction* vload = new (GetAllocator()) HVecLoad( - GetAllocator(), - array, - index, - DataType::Type::kInt32, - SideEffects::ArrayReadOfType(DataType::Type::kInt32), - 4, - /*is_string_char_at*/ false, - kNoDexPc); - block->InsertInstructionBefore(vload, block->GetLastInstruction()); - return vload; - } - - HInstruction* AddVecStore(HBasicBlock* block, - HInstruction* array, - HInstruction* index, - HVecOperation* vdata = nullptr) { - DCHECK(block != nullptr); - DCHECK(array != nullptr); - DCHECK(index != nullptr); - if (vdata == nullptr) { - HInstruction* c1 = graph_->GetIntConstant(1); - vdata = new (GetAllocator()) HVecReplicateScalar(GetAllocator(), - c1, - DataType::Type::kInt32, - 4, - kNoDexPc); - block->InsertInstructionBefore(vdata, block->GetLastInstruction()); - } - HInstruction* vstore = new (GetAllocator()) HVecStore( - GetAllocator(), - array, - index, - vdata, - DataType::Type::kInt32, - SideEffects::ArrayWriteOfType(DataType::Type::kInt32), - 4, - kNoDexPc); - block->InsertInstructionBefore(vstore, block->GetLastInstruction()); - return vstore; - } - - HInstruction* AddArrayGet(HBasicBlock* block, HInstruction* array, HInstruction* index) { - DCHECK(block != nullptr); - DCHECK(array != nullptr); - DCHECK(index != nullptr); - HInstruction* get = new (GetAllocator()) HArrayGet(array, index, DataType::Type::kInt32, 0); - block->InsertInstructionBefore(get, block->GetLastInstruction()); - return get; - } - - HInstruction* AddArraySet(HBasicBlock* block, - HInstruction* array, - HInstruction* index, - HInstruction* data = nullptr) { - DCHECK(block != nullptr); - DCHECK(array != nullptr); - DCHECK(index != nullptr); - if (data == nullptr) { - data = graph_->GetIntConstant(1); - } - HInstruction* store = new (GetAllocator()) HArraySet(array, - index, - data, - DataType::Type::kInt32, - 0); - block->InsertInstructionBefore(store, block->GetLastInstruction()); - return store; - } - - ArenaPool pool_; - - HGraph* graph_; - HBasicBlock* entry_; - HBasicBlock* pre_header_; - HBasicBlock* loop_header_; - HBasicBlock* loop_body_; - HBasicBlock* exit_; - - HInstruction* array_; - HInstruction* i_; - HInstruction* j_; - HInstruction* i_add1_; - HInstruction* i_add4_; - - HPhi* phi_; - HInstruction* cmp_; - HInstruction* if_; -}; - -TEST_F(LoadStoreEliminationTest, ArrayGetSetElimination) { - CreateTestControlFlowGraph(); - - HInstruction* c1 = graph_->GetIntConstant(1); - HInstruction* c2 = graph_->GetIntConstant(2); - HInstruction* c3 = graph_->GetIntConstant(3); - - // array[1] = 1; - // x = array[1]; <--- Remove. - // y = array[2]; - // array[1] = 1; <--- Remove, since it stores same value. - // array[i] = 3; <--- MAY alias. - // array[1] = 1; <--- Cannot remove, even if it stores the same value. - AddArraySet(entry_, array_, c1, c1); - HInstruction* load1 = AddArrayGet(entry_, array_, c1); - HInstruction* load2 = AddArrayGet(entry_, array_, c2); - HInstruction* store1 = AddArraySet(entry_, array_, c1, c1); - AddArraySet(entry_, array_, i_, c3); - HInstruction* store2 = AddArraySet(entry_, array_, c1, c1); - - PerformLSE(); - - ASSERT_TRUE(IsRemoved(load1)); - ASSERT_FALSE(IsRemoved(load2)); - ASSERT_TRUE(IsRemoved(store1)); - ASSERT_FALSE(IsRemoved(store2)); -} - -TEST_F(LoadStoreEliminationTest, SameHeapValue) { - CreateTestControlFlowGraph(); - - HInstruction* c1 = graph_->GetIntConstant(1); - HInstruction* c2 = graph_->GetIntConstant(2); - - // Test LSE handling same value stores on array. - // array[1] = 1; - // array[2] = 1; - // array[1] = 1; <--- Can remove. - // array[1] = 2; <--- Can NOT remove. - AddArraySet(entry_, array_, c1, c1); - AddArraySet(entry_, array_, c2, c1); - HInstruction* store1 = AddArraySet(entry_, array_, c1, c1); - HInstruction* store2 = AddArraySet(entry_, array_, c1, c2); - - // Test LSE handling same value stores on vector. - // vdata = [0x1, 0x2, 0x3, 0x4, ...] - // VecStore array[i...] = vdata; - // VecStore array[j...] = vdata; <--- MAY ALIAS. - // VecStore array[i...] = vdata; <--- Cannot Remove, even if it's same value. - AddVecStore(entry_, array_, i_); - AddVecStore(entry_, array_, j_); - HInstruction* vstore1 = AddVecStore(entry_, array_, i_); - - // VecStore array[i...] = vdata; - // VecStore array[i+1...] = vdata; <--- MAY alias due to partial overlap. - // VecStore array[i...] = vdata; <--- Cannot remove, even if it's same value. - AddVecStore(entry_, array_, i_); - AddVecStore(entry_, array_, i_add1_); - HInstruction* vstore2 = AddVecStore(entry_, array_, i_); - - PerformLSE(); - - ASSERT_TRUE(IsRemoved(store1)); - ASSERT_FALSE(IsRemoved(store2)); - ASSERT_FALSE(IsRemoved(vstore1)); - ASSERT_FALSE(IsRemoved(vstore2)); -} - -TEST_F(LoadStoreEliminationTest, OverlappingLoadStore) { - CreateTestControlFlowGraph(); - - HInstruction* c1 = graph_->GetIntConstant(1); - - // Test LSE handling array LSE when there is vector store in between. - // a[i] = 1; - // .. = a[i]; <-- Remove. - // a[i,i+1,i+2,i+3] = data; <-- PARTIAL OVERLAP ! - // .. = a[i]; <-- Cannot remove. - AddArraySet(entry_, array_, i_, c1); - HInstruction* load1 = AddArrayGet(entry_, array_, i_); - AddVecStore(entry_, array_, i_); - HInstruction* load2 = AddArrayGet(entry_, array_, i_); - - // Test LSE handling vector load/store partial overlap. - // a[i,i+1,i+2,i+3] = data; - // a[i+4,i+5,i+6,i+7] = data; - // .. = a[i,i+1,i+2,i+3]; - // .. = a[i+4,i+5,i+6,i+7]; - // a[i+1,i+2,i+3,i+4] = data; <-- PARTIAL OVERLAP ! - // .. = a[i,i+1,i+2,i+3]; - // .. = a[i+4,i+5,i+6,i+7]; - AddVecStore(entry_, array_, i_); - AddVecStore(entry_, array_, i_add4_); - HInstruction* vload1 = AddVecLoad(entry_, array_, i_); - HInstruction* vload2 = AddVecLoad(entry_, array_, i_add4_); - AddVecStore(entry_, array_, i_add1_); - HInstruction* vload3 = AddVecLoad(entry_, array_, i_); - HInstruction* vload4 = AddVecLoad(entry_, array_, i_add4_); - - // Test LSE handling vector LSE when there is array store in between. - // a[i,i+1,i+2,i+3] = data; - // a[i+1] = 1; <-- PARTIAL OVERLAP ! - // .. = a[i,i+1,i+2,i+3]; - AddVecStore(entry_, array_, i_); - AddArraySet(entry_, array_, i_, c1); - HInstruction* vload5 = AddVecLoad(entry_, array_, i_); - - PerformLSE(); - - ASSERT_TRUE(IsRemoved(load1)); - ASSERT_FALSE(IsRemoved(load2)); - - ASSERT_TRUE(IsRemoved(vload1)); - ASSERT_TRUE(IsRemoved(vload2)); - ASSERT_FALSE(IsRemoved(vload3)); - ASSERT_FALSE(IsRemoved(vload4)); - - ASSERT_FALSE(IsRemoved(vload5)); -} - -// function (int[] a, int j) { -// a[j] = 1; -// for (int i=0; i<128; i++) { -// /* doesn't do any write */ -// } -// a[j] = 1; -TEST_F(LoadStoreEliminationTest, Loop1) { - CreateTestControlFlowGraph(); - - HInstruction* c1 = graph_->GetIntConstant(1); - - // a[j] = 1 - AddArraySet(pre_header_, array_, j_, c1); - - // LOOP BODY: - // .. = a[i,i+1,i+2,i+3]; - AddVecLoad(loop_body_, array_, phi_); - - // a[j] = 1; - HInstruction* array_set = AddArraySet(exit_, array_, j_, c1); - - PerformLSE(); - - ASSERT_TRUE(IsRemoved(array_set)); -} - -// function (int[] a, int index) { -// a[index] = 1; -// int[] b = new int[128]; -// for (int i=0; i<128; i++) { -// a[i,i+1,i+2,i+3] = vdata; -// b[i,i+1,i+2,i+3] = a[i,i+1,i+2,i+3]; -// } -// a[index] = 1; -// } -TEST_F(LoadStoreEliminationTest, Loop2) { - CreateTestControlFlowGraph(); - - HInstruction* c0 = graph_->GetIntConstant(0); - HInstruction* c1 = graph_->GetIntConstant(1); - HInstruction* c128 = graph_->GetIntConstant(128); - - HInstruction* array_b = new (GetAllocator()) HNewArray(c0, c128, 0); - entry_->AddInstruction(array_b); - - // a[index] = 1; - AddArraySet(pre_header_, array_, i_, c1); - - // a[i,i+1,i+2,i+3] = vdata; - // b[i,i+1,i+2,i+3] = a[i,i+1,i+2,i+3]; - AddVecStore(loop_body_, array_, phi_); - HInstruction* vload = AddVecLoad(loop_body_, array_, phi_); - AddVecStore(loop_body_, array_b, phi_, vload->AsVecLoad()); - - // a[index] = 1; - HInstruction* a_set = AddArraySet(exit_, array_, i_, c1); - - PerformLSE(); - - ASSERT_TRUE(IsRemoved(vload)); - ASSERT_FALSE(IsRemoved(a_set)); // Cannot remove due to side effect in loop. -} - -} // namespace art diff --git a/test/165-lock-owner-proxy/src/Main.java b/test/165-lock-owner-proxy/src/Main.java index 1b1694d2c1..fff8e58606 100644 --- a/test/165-lock-owner-proxy/src/Main.java +++ b/test/165-lock-owner-proxy/src/Main.java @@ -65,8 +65,13 @@ public class Main { int count = totalOperations; while (count > 0) { synchronized (lockObject) { - inf.foo(10000 - count, 11000 - count, 12000 - count, 13000 - count, - 14000 - count, 15000 - count); + try { + inf.foo(10000 - count, 11000 - count, 12000 - count, 13000 - count, + 14000 - count, 15000 - count); + } catch (OutOfMemoryError e) { + // Ignore errors. This is the test for b/69121347 - see an exception + // instead of native abort. + } } count--; } @@ -96,7 +101,12 @@ public class Main { while (!finish) { // Some random allocations adding up to almost 2M. for (int i = 0; i < 188; i++) { - byte b[] = new byte[i * 100 + 10]; + try { + byte b[] = new byte[i * 100 + 10]; + } catch (OutOfMemoryError e) { + // Ignore. This is just to improve chances that an OOME is thrown during + // proxy invocation. + } } try { Thread.sleep(10); diff --git a/test/913-heaps/build b/test/913-heaps/build deleted file mode 100644 index 10ffcc537d..0000000000 --- a/test/913-heaps/build +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -# -# Copyright 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# See b/65168732 -export USE_D8=false - -./default-build "$@" diff --git a/test/913-heaps/check b/test/913-heaps/check index 835850004a..f4892d0a07 100644 --- a/test/913-heaps/check +++ b/test/913-heaps/check @@ -14,9 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Jack has a different set of bytecode offsets/method IDs in the expected.txt +# Jack/D8 has a different set of bytecode offsets/method IDs in the expected.txt + if [[ "$USE_JACK" == true ]]; then patch -p0 expected.txt < expected_jack.diff +elif [[ "$USE_D8" == true ]]; then + patch -p0 expected.txt < expected_d8.diff fi ./default-check "$@" diff --git a/test/913-heaps/expected_d8.diff b/test/913-heaps/expected_d8.diff new file mode 100644 index 0000000000..83694220a3 --- /dev/null +++ b/test/913-heaps/expected_d8.diff @@ -0,0 +1,76 @@ +4,5c4 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 30])--> 1@1000 [size=16, length=-1] +< root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=136, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1] +49c48 +< root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=11,location= 8])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] +51c50,51 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 21])--> 1@1000 [size=16, length=-1] +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=8,location= 21])--> 1@1000 [size=16, length=-1] +102,103c102 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 30])--> 1@1000 [size=16, length=-1] +< root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=136, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1] +115c114 +< root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=11,location= 8])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] +117c116,117 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 21])--> 1@1000 [size=16, length=-1] +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=8,location= 21])--> 1@1000 [size=16, length=-1] +162c162 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 30])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1] +177c177 +< root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=11,location= 8])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] +179c179,180 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 21])--> 1@1000 [size=16, length=-1] +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=8,location= 21])--> 1@1000 [size=16, length=-1] +201,202c202,203 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 30])--> 1@1000 [size=16, length=-1] +< root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=136, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1] +> root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 164])--> 1000@0 [size=123456780050, length=-1] +246c247 +< root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=11,location= 8])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] +248c249,251 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 21])--> 1@1000 [size=16, length=-1] +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=8,location= 21])--> 1@1000 [size=16, length=-1] +> root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 164])--> 1000@0 [size=123456780055, length=-1] +292c295 +< root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=136, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 181])--> 1000@0 [size=123456780060, length=-1] +319a323 +> root@root --(stack-local[id=1,tag=3000,depth=4,method=runFollowReferences,vreg=3,location= 181])--> 1000@0 [size=123456780065, length=-1] +347c351 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 30])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1] +366c370 +< root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=11,location= 8])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] +368c372,373 +< root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1] +--- +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 21])--> 1@1000 [size=16, length=-1] +> root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=8,location= 21])--> 1@1000 [size=16, length=-1] |