summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2016-03-23 16:01:47 +0000
committer Vladimir Marko <vmarko@google.com> 2016-03-23 19:17:51 +0000
commitd96a246e5b103bfc167acaa6315bd8abca9de493 (patch)
tree3e99f24bc30d53bc9cfc9fb1e0f3dc92c0ce1daf /compiler/optimizing
parent3920099f578fd8015777bc3c1c7392a08b1e08e7 (diff)
Optimizing: Do not insert suspend checks on back-edges.
Rely on HGraph::SimplifyLoop() to insert suspend checks. CodeGenerator's CheckLoopEntriesCanBeUsedForOsr() checks the dex pcs of suspend checks against branch targets to verify that we always have an appropriate point for OSR transition. However, the HSuspendChecks that were added by HGraphBuilder to support the recently removed "baseline" interfered with this in a specific case, namely an infinite loop where the back-branch jumps to a nop. In that case, the HSuspendCheck added by HGraphBuilder had a dex pc different from the block and the branch target but its presence would stop the HGraph::SimplifyLoop() from adding a new HSuspendCheck with the correct dex pc. Bug: 27623547 Change-Id: I83566a260210bc05aea0c44509a39bb490aa7003
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/builder.cc21
-rw-r--r--compiler/optimizing/builder.h1
-rw-r--r--compiler/optimizing/constant_folding_test.cc51
-rw-r--r--compiler/optimizing/dead_code_elimination_test.cc36
-rw-r--r--compiler/optimizing/instruction_simplifier.cc17
-rw-r--r--compiler/optimizing/pretty_printer_test.cc22
6 files changed, 46 insertions, 102 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 124afbc73b..483bdd562f 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -106,7 +106,6 @@ void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) {
HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
DCHECK(branch_target != nullptr);
DCHECK(fallthrough_target != nullptr);
- PotentiallyAddSuspendCheck(branch_target, dex_pc);
HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
T* comparison = new (arena_) T(first, second, dex_pc);
@@ -125,7 +124,6 @@ void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) {
HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
DCHECK(branch_target != nullptr);
DCHECK(fallthrough_target != nullptr);
- PotentiallyAddSuspendCheck(branch_target, dex_pc);
HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
T* comparison = new (arena_) T(value, graph_->GetIntConstant(0, dex_pc), dex_pc);
current_block_->AddInstruction(comparison);
@@ -1788,7 +1786,6 @@ void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t
int32_t target_offset, uint32_t dex_pc) {
HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset);
DCHECK(case_target != nullptr);
- PotentiallyAddSuspendCheck(case_target, dex_pc);
// The current case's value.
HInstruction* this_case_value = graph_->GetIntConstant(case_value_int, dex_pc);
@@ -1824,23 +1821,6 @@ void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t
}
}
-void HGraphBuilder::PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc) {
- int32_t target_offset = target->GetDexPc() - dex_pc;
- if (target_offset <= 0) {
- // DX generates back edges to the first encountered return. We can save
- // time of later passes by not adding redundant suspend checks.
- HInstruction* last_in_target = target->GetLastInstruction();
- if (last_in_target != nullptr &&
- (last_in_target->IsReturn() || last_in_target->IsReturnVoid())) {
- return;
- }
-
- // Add a suspend check to backward branches which may potentially loop. We
- // can remove them after we recognize loops in the graph.
- current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_pc));
- }
-}
-
bool HGraphBuilder::CanDecodeQuickenedInfo() const {
return interpreter_metadata_ != nullptr;
}
@@ -1972,7 +1952,6 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32
int32_t offset = instruction.GetTargetOffset();
HBasicBlock* target = FindBlockStartingAt(offset + dex_pc);
DCHECK(target != nullptr);
- PotentiallyAddSuspendCheck(target, dex_pc);
current_block_->AddInstruction(new (arena_) HGoto(dex_pc));
current_block_->AddSuccessor(target);
current_block_ = nullptr;
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index e3dd0e8216..48f5316222 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -133,7 +133,6 @@ class HGraphBuilder : public ValueObject {
HLocal* GetLocalAt(uint32_t register_index) const;
void UpdateLocal(uint32_t register_index, HInstruction* instruction, uint32_t dex_pc) const;
HInstruction* LoadLocal(uint32_t register_index, Primitive::Type type, uint32_t dex_pc) const;
- void PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc);
void InitializeParameters(uint16_t number_of_parameters);
// Returns whether the current method needs access check for the type.
diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc
index 9c69f8c75b..1e54a0adfa 100644
--- a/compiler/optimizing/constant_folding_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -598,42 +598,41 @@ TEST_F(ConstantFoldingTest, IntConstantFoldingAndJumps) {
" 5: IntConstant [9]\n" // v1 <- 2
" 13: IntConstant [14]\n" // const 5
" 18: IntConstant [19]\n" // const 4
- " 24: IntConstant [25]\n" // const 8
- " 30: SuspendCheck\n"
- " 31: Goto 1\n"
+ " 23: IntConstant [24]\n" // const 8
+ " 29: SuspendCheck\n"
+ " 30: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 3\n"
" 9: Add(3, 5) [19]\n" // v2 <- v0 + v1 = 1 + 2 = 3
" 11: Goto 3\n" // goto L2
"BasicBlock 2, pred: 3, succ: 4\n" // L1:
- " 14: Add(19, 13) [25]\n" // v1 <- v0 + 3 = 7 + 5 = 12
+ " 14: Add(19, 13) [24]\n" // v1 <- v0 + 3 = 7 + 5 = 12
" 16: Goto 4\n" // goto L3
"BasicBlock 3, pred: 1, succ: 2\n" // L2:
" 19: Add(9, 18) [14]\n" // v0 <- v2 + 2 = 3 + 4 = 7
- " 21: SuspendCheck\n"
- " 22: Goto 2\n" // goto L1
+ " 21: Goto 2\n" // goto L1
"BasicBlock 4, pred: 2, succ: 5\n" // L3:
- " 25: Add(14, 24) [28]\n" // v2 <- v1 + 4 = 12 + 8 = 20
- " 28: Return(25)\n" // return v2
+ " 24: Add(14, 23) [27]\n" // v2 <- v1 + 4 = 12 + 8 = 20
+ " 27: Return(24)\n" // return v2
"BasicBlock 5, pred: 4\n"
- " 29: Exit\n";
+ " 28: Exit\n";
// Expected difference after constant folding.
diff_t expected_cf_diff = {
{ " 3: IntConstant [9]\n", " 3: IntConstant\n" },
- { " 5: IntConstant [9]\n", " 5: IntConstant []\n" },
+ { " 5: IntConstant [9]\n", " 5: IntConstant\n" },
{ " 13: IntConstant [14]\n", " 13: IntConstant\n" },
{ " 18: IntConstant [19]\n", " 18: IntConstant\n" },
- { " 24: IntConstant [25]\n", " 24: IntConstant\n" },
- { " 30: SuspendCheck\n", " 30: SuspendCheck\n"
- " 32: IntConstant []\n"
- " 33: IntConstant []\n"
- " 34: IntConstant\n"
- " 35: IntConstant [28]\n" },
+ { " 23: IntConstant [24]\n", " 23: IntConstant\n" },
+ { " 29: SuspendCheck\n", " 29: SuspendCheck\n"
+ " 31: IntConstant\n"
+ " 32: IntConstant\n"
+ " 33: IntConstant\n"
+ " 34: IntConstant [27]\n" },
{ " 9: Add(3, 5) [19]\n", removed },
- { " 14: Add(19, 13) [25]\n", removed },
+ { " 14: Add(19, 13) [24]\n", removed },
{ " 19: Add(9, 18) [14]\n", removed },
- { " 25: Add(14, 24) [28]\n", removed },
- { " 28: Return(25)\n", " 28: Return(35)\n"}
+ { " 24: Add(14, 23) [27]\n", removed },
+ { " 27: Return(24)\n", " 27: Return(34)\n"}
};
std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
@@ -656,17 +655,13 @@ TEST_F(ConstantFoldingTest, IntConstantFoldingAndJumps) {
// Expected difference after dead code elimination.
std::string expected_after_dce =
"BasicBlock 0, succ: 1\n"
- " 5: IntConstant []\n"
- " 30: SuspendCheck\n"
- " 32: IntConstant []\n"
- " 33: IntConstant []\n"
- " 35: IntConstant [28]\n"
- " 31: Goto 1\n"
+ " 29: SuspendCheck\n"
+ " 34: IntConstant [27]\n"
+ " 30: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 5\n"
- " 21: SuspendCheck\n"
- " 28: Return(35)\n"
+ " 27: Return(34)\n"
"BasicBlock 5, pred: 1\n"
- " 29: Exit\n";
+ " 28: Exit\n";
TestCode(data,
expected_before,
diff --git a/compiler/optimizing/dead_code_elimination_test.cc b/compiler/optimizing/dead_code_elimination_test.cc
index 930795b4f6..83e724ba29 100644
--- a/compiler/optimizing/dead_code_elimination_test.cc
+++ b/compiler/optimizing/dead_code_elimination_test.cc
@@ -149,44 +149,32 @@ TEST_F(DeadCodeEliminationTest, AdditionsAndInconditionalJumps) {
" 5: IntConstant [9]\n"
" 13: IntConstant [14]\n"
" 18: IntConstant [19]\n"
- " 24: IntConstant [25]\n"
- " 29: SuspendCheck\n"
- " 30: Goto 1\n"
+ " 23: IntConstant [24]\n"
+ " 28: SuspendCheck\n"
+ " 29: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 3\n"
" 9: Add(3, 5) [19]\n"
" 11: Goto 3\n"
"BasicBlock 2, pred: 3, succ: 4\n"
- " 14: Add(19, 13) [25]\n"
+ " 14: Add(19, 13) [24]\n"
" 16: Goto 4\n"
"BasicBlock 3, pred: 1, succ: 2\n"
" 19: Add(9, 18) [14]\n"
- " 21: SuspendCheck\n"
- " 22: Goto 2\n"
+ " 21: Goto 2\n"
"BasicBlock 4, pred: 2, succ: 5\n"
- " 25: Add(14, 24)\n"
- " 27: ReturnVoid\n"
+ " 24: Add(14, 23)\n"
+ " 26: ReturnVoid\n"
"BasicBlock 5, pred: 4\n"
- " 28: Exit\n";
+ " 27: Exit\n";
- // The SuspendCheck instruction following this Add instruction
- // inserts the latter in an environment, thus making it "used" and
- // therefore non removable. It ensures that some other Add and
- // IntConstant instructions cannot be removed, as they are direct
- // or indirect inputs of the initial Add instruction.
std::string expected_after =
"BasicBlock 0, succ: 1\n"
- " 3: IntConstant [9]\n"
- " 5: IntConstant [9]\n"
- " 18: IntConstant [19]\n"
- " 29: SuspendCheck\n"
- " 30: Goto 1\n"
+ " 28: SuspendCheck\n"
+ " 29: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 5\n"
- " 9: Add(3, 5) [19]\n"
- " 19: Add(9, 18) []\n"
- " 21: SuspendCheck\n"
- " 27: ReturnVoid\n"
+ " 26: ReturnVoid\n"
"BasicBlock 5, pred: 1\n"
- " 28: Exit\n";
+ " 27: Exit\n";
TestCode(data, expected_before, expected_after);
}
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 820c696033..58f333eb87 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -56,7 +56,6 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor {
bool TryDeMorganNegationFactoring(HBinaryOperation* op);
void VisitShift(HBinaryOperation* shift);
- void VisitSuspendCheck(HSuspendCheck* check) OVERRIDE;
void VisitEqual(HEqual* equal) OVERRIDE;
void VisitNotEqual(HNotEqual* equal) OVERRIDE;
void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE;
@@ -554,22 +553,6 @@ void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruct
}
}
-void InstructionSimplifierVisitor::VisitSuspendCheck(HSuspendCheck* check) {
- HBasicBlock* block = check->GetBlock();
- // Currently always keep the suspend check at entry.
- if (block->IsEntryBlock()) return;
-
- // Currently always keep suspend checks at loop entry.
- if (block->IsLoopHeader() && block->GetFirstInstruction() == check) {
- DCHECK(block->GetLoopInformation()->GetSuspendCheck() == check);
- return;
- }
-
- // Remove the suspend check that was added at build time for the baseline
- // compiler.
- block->RemoveInstruction(check);
-}
-
static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* arena, HInstruction* cond) {
HInstruction *lhs = cond->InputAt(0);
HInstruction *rhs = cond->InputAt(1);
diff --git a/compiler/optimizing/pretty_printer_test.cc b/compiler/optimizing/pretty_printer_test.cc
index 2de0c1be72..d5b95d284a 100644
--- a/compiler/optimizing/pretty_printer_test.cc
+++ b/compiler/optimizing/pretty_printer_test.cc
@@ -135,13 +135,13 @@ TEST_F(PrettyPrinterTest, CFG3) {
TEST_F(PrettyPrinterTest, CFG4) {
const char* expected =
"BasicBlock 0, succ: 3\n"
- " 3: SuspendCheck\n"
- " 4: Goto 3\n"
+ " 2: SuspendCheck\n"
+ " 3: Goto 3\n"
"BasicBlock 1, pred: 3, 1, succ: 1\n"
- " 0: SuspendCheck\n"
- " 1: Goto 1\n"
+ " 5: SuspendCheck\n"
+ " 0: Goto 1\n"
"BasicBlock 3, pred: 0, succ: 1\n"
- " 5: Goto 1\n";
+ " 4: Goto 1\n";
const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Instruction::NOP,
@@ -204,20 +204,20 @@ TEST_F(PrettyPrinterTest, CFG7) {
const char* expected =
"BasicBlock 0, succ: 1\n"
" 1: IntConstant [5, 5]\n"
- " 11: SuspendCheck\n"
- " 12: Goto 1\n"
+ " 10: SuspendCheck\n"
+ " 11: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 5, 6\n"
" 5: Equal(1, 1) [6]\n"
" 6: If(5)\n"
"BasicBlock 2, pred: 6, 3, succ: 3\n"
" 7: Goto 3\n"
"BasicBlock 3, pred: 5, 2, succ: 2\n"
- " 8: SuspendCheck\n"
- " 9: Goto 2\n"
+ " 14: SuspendCheck\n"
+ " 8: Goto 2\n"
"BasicBlock 5, pred: 1, succ: 3\n"
- " 13: Goto 3\n"
+ " 12: Goto 3\n"
"BasicBlock 6, pred: 1, succ: 2\n"
- " 14: Goto 2\n";
+ " 13: Goto 2\n";
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,