summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/bounds_check_elimination.cc2
-rw-r--r--compiler/optimizing/instruction_builder.cc2
-rw-r--r--compiler/optimizing/licm.cc8
-rw-r--r--compiler/optimizing/loop_optimization.cc2
-rw-r--r--compiler/optimizing/nodes.cc55
-rw-r--r--compiler/optimizing/nodes.h55
-rw-r--r--compiler/optimizing/nodes_test.cc4
-rw-r--r--compiler/optimizing/optimizing_unit_test.h2
-rw-r--r--compiler/optimizing/scheduler_test.cc4
-rw-r--r--compiler/optimizing/superblock_cloner.cc2
10 files changed, 82 insertions, 54 deletions
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index c0d4c37659..1ef4d751a2 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -1983,7 +1983,7 @@ class BCEVisitor final : public HGraphVisitor {
}
user->RemoveAsUserOfInput(index);
user->SetRawEnvAt(index, phi);
- phi->AddEnvUseAt(user, index);
+ phi->AddEnvUseAt(GetGraph()->GetAllocator(), user, index);
}
}
}
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 1f2628c8ec..74880463c3 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -305,7 +305,7 @@ void HInstructionBuilder::InitializeInstruction(HInstruction* instruction) {
graph_->GetArtMethod(),
instruction->GetDexPc(),
instruction);
- environment->CopyFrom(ArrayRef<HInstruction* const>(*current_locals_));
+ environment->CopyFrom(allocator_, ArrayRef<HInstruction* const>(*current_locals_));
instruction->SetRawEnvironment(environment);
}
}
diff --git a/compiler/optimizing/licm.cc b/compiler/optimizing/licm.cc
index 0c791b640d..729a277ee0 100644
--- a/compiler/optimizing/licm.cc
+++ b/compiler/optimizing/licm.cc
@@ -64,7 +64,9 @@ static bool InputsAreDefinedBeforeLoop(HInstruction* instruction) {
/**
* If `environment` has a loop header phi, we replace it with its first input.
*/
-static void UpdateLoopPhisIn(HEnvironment* environment, HLoopInformation* info) {
+static void UpdateLoopPhisIn(ArenaAllocator* allocator,
+ HEnvironment* environment,
+ HLoopInformation* info) {
for (; environment != nullptr; environment = environment->GetParent()) {
for (size_t i = 0, e = environment->Size(); i < e; ++i) {
HInstruction* input = environment->GetInstructionAt(i);
@@ -72,7 +74,7 @@ static void UpdateLoopPhisIn(HEnvironment* environment, HLoopInformation* info)
environment->RemoveAsUserOfInput(i);
HInstruction* incoming = input->InputAt(0);
environment->SetRawEnvAt(i, incoming);
- incoming->AddEnvUseAt(environment, i);
+ incoming->AddEnvUseAt(allocator, environment, i);
}
}
}
@@ -152,7 +154,7 @@ bool LICM::Run() {
// We need to update the environment if the instruction has a loop header
// phi in it.
if (instruction->NeedsEnvironment()) {
- UpdateLoopPhisIn(instruction->GetEnvironment(), loop_info);
+ UpdateLoopPhisIn(graph_->GetAllocator(), instruction->GetEnvironment(), loop_info);
} else {
DCHECK(!instruction->HasEnvironment());
}
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 2f1aea68aa..18b2b56d00 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -3095,7 +3095,7 @@ bool HLoopOptimization::TryReplaceWithLastValue(HLoopInformation* loop_info,
if (other_loop_info == nullptr || !other_loop_info->IsIn(*loop_info)) {
user->RemoveAsUserOfInput(index);
user->SetRawEnvAt(index, replacement);
- replacement->AddEnvUseAt(user, index);
+ replacement->AddEnvUseAt(graph_->GetAllocator(), user, index);
}
}
}
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 6be474a8c9..ae5e73ad0d 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -1035,10 +1035,13 @@ bool HBasicBlock::Dominates(const HBasicBlock* other) const {
return false;
}
-static void UpdateInputsUsers(HInstruction* instruction) {
+static void UpdateInputsUsers(HGraph* graph, HInstruction* instruction) {
HInputsRef inputs = instruction->GetInputs();
- for (size_t i = 0; i < inputs.size(); ++i) {
- inputs[i]->AddUseAt(instruction, i);
+ if (inputs.size() != 0u) {
+ ArenaAllocator* allocator = graph->GetAllocator();
+ for (size_t i = 0; i < inputs.size(); ++i) {
+ inputs[i]->AddUseAt(allocator, instruction, i);
+ }
}
// Environment should be created later.
DCHECK(!instruction->HasEnvironment());
@@ -1064,9 +1067,10 @@ void HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial,
DCHECK(initial->GetUses().empty());
DCHECK(initial->GetEnvUses().empty());
replacement->SetBlock(this);
- replacement->SetId(GetGraph()->GetNextInstructionId());
+ HGraph* graph = GetGraph();
+ replacement->SetId(graph->GetNextInstructionId());
instructions_.InsertInstructionBefore(replacement, initial);
- UpdateInputsUsers(replacement);
+ UpdateInputsUsers(graph, replacement);
} else {
InsertInstructionBefore(replacement, initial);
initial->ReplaceWith(replacement);
@@ -1080,8 +1084,9 @@ static void Add(HInstructionList* instruction_list,
DCHECK(instruction->GetBlock() == nullptr);
DCHECK_EQ(instruction->GetId(), -1);
instruction->SetBlock(block);
- instruction->SetId(block->GetGraph()->GetNextInstructionId());
- UpdateInputsUsers(instruction);
+ HGraph* graph = block->GetGraph();
+ instruction->SetId(graph->GetNextInstructionId());
+ UpdateInputsUsers(graph, instruction);
instruction_list->AddInstruction(instruction);
}
@@ -1101,8 +1106,9 @@ void HBasicBlock::InsertInstructionBefore(HInstruction* instruction, HInstructio
DCHECK_EQ(cursor->GetBlock(), this);
DCHECK(!instruction->IsControlFlow());
instruction->SetBlock(this);
- instruction->SetId(GetGraph()->GetNextInstructionId());
- UpdateInputsUsers(instruction);
+ HGraph* graph = GetGraph();
+ instruction->SetId(graph->GetNextInstructionId());
+ UpdateInputsUsers(graph, instruction);
instructions_.InsertInstructionBefore(instruction, cursor);
}
@@ -1115,8 +1121,9 @@ void HBasicBlock::InsertInstructionAfter(HInstruction* instruction, HInstruction
DCHECK(!instruction->IsControlFlow());
DCHECK(!cursor->IsControlFlow());
instruction->SetBlock(this);
- instruction->SetId(GetGraph()->GetNextInstructionId());
- UpdateInputsUsers(instruction);
+ HGraph* graph = GetGraph();
+ instruction->SetId(graph->GetNextInstructionId());
+ UpdateInputsUsers(graph, instruction);
instructions_.InsertInstructionAfter(instruction, cursor);
}
@@ -1125,8 +1132,9 @@ void HBasicBlock::InsertPhiAfter(HPhi* phi, HPhi* cursor) {
DCHECK_NE(cursor->GetId(), -1);
DCHECK_EQ(cursor->GetBlock(), this);
phi->SetBlock(this);
- phi->SetId(GetGraph()->GetNextInstructionId());
- UpdateInputsUsers(phi);
+ HGraph* graph = GetGraph();
+ phi->SetId(graph->GetNextInstructionId());
+ UpdateInputsUsers(graph, phi);
phis_.InsertInstructionAfter(phi, cursor);
}
@@ -1161,27 +1169,30 @@ void HBasicBlock::RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_
}
}
-void HEnvironment::CopyFrom(ArrayRef<HInstruction* const> locals) {
+void HEnvironment::CopyFrom(ArenaAllocator* allocator, ArrayRef<HInstruction* const> locals) {
+ DCHECK_EQ(locals.size(), Size());
for (size_t i = 0; i < locals.size(); i++) {
HInstruction* instruction = locals[i];
SetRawEnvAt(i, instruction);
if (instruction != nullptr) {
- instruction->AddEnvUseAt(this, i);
+ instruction->AddEnvUseAt(allocator, this, i);
}
}
}
-void HEnvironment::CopyFrom(const HEnvironment* env) {
+void HEnvironment::CopyFrom(ArenaAllocator* allocator, const HEnvironment* env) {
+ DCHECK_EQ(env->Size(), Size());
for (size_t i = 0; i < env->Size(); i++) {
HInstruction* instruction = env->GetInstructionAt(i);
SetRawEnvAt(i, instruction);
if (instruction != nullptr) {
- instruction->AddEnvUseAt(this, i);
+ instruction->AddEnvUseAt(allocator, this, i);
}
}
}
-void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,
+void HEnvironment::CopyFromWithLoopPhiAdjustment(ArenaAllocator* allocator,
+ HEnvironment* env,
HBasicBlock* loop_header) {
DCHECK(loop_header->IsLoopHeader());
for (size_t i = 0; i < env->Size(); i++) {
@@ -1195,9 +1206,9 @@ void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,
// is the first input of the phi.
HInstruction* initial = instruction->AsPhi()->InputAt(0);
SetRawEnvAt(i, initial);
- initial->AddEnvUseAt(this, i);
+ initial->AddEnvUseAt(allocator, this, i);
} else {
- instruction->AddEnvUseAt(this, i);
+ instruction->AddEnvUseAt(allocator, this, i);
}
}
}
@@ -1538,7 +1549,7 @@ size_t HInstruction::EnvironmentSize() const {
void HVariableInputSizeInstruction::AddInput(HInstruction* input) {
DCHECK(input->GetBlock() != nullptr);
inputs_.push_back(HUserRecord<HInstruction*>(input));
- input->AddUseAt(this, inputs_.size() - 1);
+ input->AddUseAt(GetBlock()->GetGraph()->GetAllocator(), this, inputs_.size() - 1);
}
void HVariableInputSizeInstruction::InsertInputAt(size_t index, HInstruction* input) {
@@ -1550,7 +1561,7 @@ void HVariableInputSizeInstruction::InsertInputAt(size_t index, HInstruction* in
}
// Add the use after updating the indexes. If the `input` is already used by `this`,
// the fixup after use insertion can use those indexes.
- input->AddUseAt(this, index);
+ input->AddUseAt(GetBlock()->GetGraph()->GetAllocator(), this, index);
}
void HVariableInputSizeInstruction::RemoveInputAt(size_t index) {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 99fbbc6357..fb56c281d9 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1893,20 +1893,22 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> {
parent_->SetAndCopyParentChain(allocator, parent);
} else {
parent_ = Create(allocator, *parent, holder_);
- parent_->CopyFrom(parent);
+ parent_->CopyFrom(allocator, parent);
if (parent->GetParent() != nullptr) {
parent_->SetAndCopyParentChain(allocator, parent->GetParent());
}
}
}
- void CopyFrom(ArrayRef<HInstruction* const> locals);
- void CopyFrom(const HEnvironment* environment);
+ void CopyFrom(ArenaAllocator* allocator, ArrayRef<HInstruction* const> locals);
+ void CopyFrom(ArenaAllocator* allocator, const HEnvironment* environment);
// Copy from `env`. If it's a loop phi for `loop_header`, copy the first
// input to the loop phi instead. This is for inserting instructions that
// require an environment (like HDeoptimization) in the loop pre-header.
- void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
+ void CopyFromWithLoopPhiAdjustment(ArenaAllocator* allocator,
+ HEnvironment* env,
+ HBasicBlock* loop_header);
void SetRawEnvAt(size_t index, HInstruction* instruction) {
GetVRegs()[index] = HUserRecord<HEnvironment*>(instruction);
@@ -2227,25 +2229,38 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
GetPackedFlag<kFlagReferenceTypeIsExact>());
}
- void AddUseAt(HInstruction* user, size_t index) {
+ void AddUseAt(ArenaAllocator* allocator, HInstruction* user, size_t index) {
DCHECK(user != nullptr);
- // Note: fixup_end remains valid across push_front().
- auto fixup_end = uses_.empty() ? uses_.begin() : ++uses_.begin();
- ArenaAllocator* allocator = user->GetBlock()->GetGraph()->GetAllocator();
HUseListNode<HInstruction*>* new_node =
new (allocator) HUseListNode<HInstruction*>(user, index);
+ // Note: `old_begin` remains valid across `push_front()`.
+ auto old_begin = uses_.begin();
uses_.push_front(*new_node);
- FixUpUserRecordsAfterUseInsertion(fixup_end);
+ auto new_begin = uses_.begin();
+ user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(this, uses_.before_begin()));
+ if (old_begin != uses_.end()) {
+ HInstruction* old_begin_user = old_begin->GetUser();
+ size_t old_begin_index = old_begin->GetIndex();
+ old_begin_user->SetRawInputRecordAt(
+ old_begin_index, HUserRecord<HInstruction*>(this, new_begin));
+ }
}
- void AddEnvUseAt(HEnvironment* user, size_t index) {
+ void AddEnvUseAt(ArenaAllocator* allocator, HEnvironment* user, size_t index) {
DCHECK(user != nullptr);
- // Note: env_fixup_end remains valid across push_front().
- auto env_fixup_end = env_uses_.empty() ? env_uses_.begin() : ++env_uses_.begin();
HUseListNode<HEnvironment*>* new_node =
- new (GetBlock()->GetGraph()->GetAllocator()) HUseListNode<HEnvironment*>(user, index);
+ new (allocator) HUseListNode<HEnvironment*>(user, index);
+ // Note: `old_env_begin` remains valid across `push_front()`.
+ auto old_env_begin = env_uses_.begin();
env_uses_.push_front(*new_node);
- FixUpUserRecordsAfterEnvUseInsertion(env_fixup_end);
+ auto new_env_begin = env_uses_.begin();
+ user->GetVRegs()[index] = HUserRecord<HEnvironment*>(this, env_uses_.before_begin());
+ if (old_env_begin != env_uses_.end()) {
+ HEnvironment* old_env_begin_user = old_env_begin->GetUser();
+ size_t old_env_begin_index = old_env_begin->GetIndex();
+ old_env_begin_user->GetVRegs()[old_env_begin_index] =
+ HUserRecord<HEnvironment*>(this, new_env_begin);
+ }
}
void RemoveAsUserOfInput(size_t input) {
@@ -2343,18 +2358,18 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
DCHECK(environment_ == nullptr);
ArenaAllocator* allocator = GetBlock()->GetGraph()->GetAllocator();
environment_ = HEnvironment::Create(allocator, *environment, this);
- environment_->CopyFrom(environment);
+ environment_->CopyFrom(allocator, environment);
if (environment->GetParent() != nullptr) {
environment_->SetAndCopyParentChain(allocator, environment->GetParent());
}
}
void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
- HBasicBlock* block) {
+ HBasicBlock* loop_header) {
DCHECK(environment_ == nullptr);
- ArenaAllocator* allocator = GetBlock()->GetGraph()->GetAllocator();
+ ArenaAllocator* allocator = loop_header->GetGraph()->GetAllocator();
environment_ = HEnvironment::Create(allocator, *environment, this);
- environment_->CopyFromWithLoopPhiAdjustment(environment, block);
+ environment_->CopyFromWithLoopPhiAdjustment(allocator, environment, loop_header);
if (environment->GetParent() != nullptr) {
environment_->SetAndCopyParentChain(allocator, environment->GetParent());
}
@@ -6845,7 +6860,7 @@ inline void HLoadClass::AddSpecialInput(HInstruction* special_input) {
GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
DCHECK(special_input_.GetInstruction() == nullptr);
special_input_ = HUserRecord<HInstruction*>(special_input);
- special_input->AddUseAt(this, 0);
+ special_input->AddUseAt(GetBlock()->GetGraph()->GetAllocator(), this, 0);
}
class HLoadString final : public HInstruction {
@@ -7013,7 +7028,7 @@ inline void HLoadString::AddSpecialInput(HInstruction* special_input) {
// so use the GetInputRecords() from the base class to set the input record.
DCHECK(special_input_.GetInstruction() == nullptr);
special_input_ = HUserRecord<HInstruction*>(special_input);
- special_input->AddUseAt(this, 0);
+ special_input->AddUseAt(GetBlock()->GetGraph()->GetAllocator(), this, 0);
}
class HLoadMethodHandle final : public HInstruction {
diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc
index 5f71d053c6..97f74cb7b9 100644
--- a/compiler/optimizing/nodes_test.cc
+++ b/compiler/optimizing/nodes_test.cc
@@ -248,7 +248,7 @@ TEST_F(NodeTest, ParentEnvironment) {
graph->GetArtMethod(),
/*dex_pc=*/ 0,
/*holder=*/ nullptr);
- parent1->CopyFrom(ArrayRef<HInstruction* const>(&parameter1, 1u));
+ parent1->CopyFrom(GetAllocator(), ArrayRef<HInstruction* const>(&parameter1, 1u));
ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u);
@@ -258,7 +258,7 @@ TEST_F(NodeTest, ParentEnvironment) {
graph->GetArtMethod(),
/*dex_pc=*/ 0,
/*holder=*/ nullptr);
- parent2->CopyFrom(ArrayRef<HInstruction* const>(&parameter1, 1u));
+ parent2->CopyFrom(GetAllocator(), ArrayRef<HInstruction* const>(&parameter1, 1u));
parent1->SetAndCopyParentChain(GetAllocator(), parent2);
// One use for parent2, and one other use for the new parent of parent1.
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index d81f3804dc..c40b918fee 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -446,7 +446,7 @@ class OptimizingUnitTestHelper {
instruction->GetDexPc(),
instruction);
- environment->CopyFrom(ArrayRef<HInstruction* const>(*current_locals));
+ environment->CopyFrom(GetAllocator(), ArrayRef<HInstruction* const>(*current_locals));
instruction->SetRawEnvironment(environment);
return environment;
}
diff --git a/compiler/optimizing/scheduler_test.cc b/compiler/optimizing/scheduler_test.cc
index 7003bd2715..6359119a87 100644
--- a/compiler/optimizing/scheduler_test.cc
+++ b/compiler/optimizing/scheduler_test.cc
@@ -118,9 +118,9 @@ class SchedulerTest : public CommonCompilerTest, public OptimizingUnitTestHelper
div_check);
div_check->SetRawEnvironment(environment);
environment->SetRawEnvAt(0, add2);
- add2->AddEnvUseAt(div_check->GetEnvironment(), 0);
+ add2->AddEnvUseAt(GetAllocator(), div_check->GetEnvironment(), 0);
environment->SetRawEnvAt(1, mul);
- mul->AddEnvUseAt(div_check->GetEnvironment(), 1);
+ mul->AddEnvUseAt(GetAllocator(), div_check->GetEnvironment(), 1);
TestSchedulingGraph scheduling_graph(GetScopedAllocator());
// Instructions must be inserted in reverse order into the scheduling graph.
diff --git a/compiler/optimizing/superblock_cloner.cc b/compiler/optimizing/superblock_cloner.cc
index a7328a1218..5ab34fb1a8 100644
--- a/compiler/optimizing/superblock_cloner.cc
+++ b/compiler/optimizing/superblock_cloner.cc
@@ -144,7 +144,7 @@ void SuperblockCloner::DeepCloneEnvironmentWithRemapping(HInstruction* copy_inst
}
copy_env->SetRawEnvAt(i, env_input);
if (env_input != nullptr) {
- env_input->AddEnvUseAt(copy_env, i);
+ env_input->AddEnvUseAt(graph_->GetAllocator(), copy_env, i);
}
}
// InsertRawEnvironment assumes that instruction already has an environment that's why we use