Merge "Move oatdump to use code item accessor"
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 1a2d9aa..8599471 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -355,7 +355,6 @@
"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 5c89869..0c82d60 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -80,6 +80,9 @@
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 @@
// 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 f9f5a4d..ddec0cc 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -2474,6 +2474,7 @@
}
}
} else {
+ const bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
MipsLabel done;
if (instr->IsShl()) {
__ Sllv(dst_low, lhs_low, rhs_reg);
@@ -2483,9 +2484,14 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 7d953c0..605fdae 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -83,8 +83,7 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 6f42d96..0000000
--- 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 1b1694d..fff8e58 100644
--- a/test/165-lock-owner-proxy/src/Main.java
+++ b/test/165-lock-owner-proxy/src/Main.java
@@ -65,8 +65,13 @@
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 @@
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 10ffcc5..0000000
--- 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 8358500..f4892d0 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 0000000..8369422
--- /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]