summaryrefslogtreecommitdiffstats
path: root/compiler/dex
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2014-07-11 14:44:36 +0100
committerVladimir Marko <vmarko@google.com>2014-07-22 19:38:24 +0100
commit0a810d2eab27cd097ebd09a44f0ce83aa608285b (patch)
tree4fae42ff559b4c5381158fad3a6fe802dd8e904b /compiler/dex
parente10a0bd05b195f71cc0ff2d59568d02d29939927 (diff)
downloadart-0a810d2eab27cd097ebd09a44f0ce83aa608285b.tar.gz
art-0a810d2eab27cd097ebd09a44f0ce83aa608285b.tar.bz2
art-0a810d2eab27cd097ebd09a44f0ce83aa608285b.zip
Fix null pointer check elimination for catch entries.
Remove the special treatment of catch blocks for null pointer check elimination and class initialization check elimination. In both cases this can help optimizing previously missed cases. In the null check case, this avoids incorrect optimization as exposed by the new test. Bug: 16230771 Change-Id: I834b7a1835d9ca8572f4f8d8516d93913c701ad1
Diffstat (limited to 'compiler/dex')
-rw-r--r--compiler/dex/mir_optimization.cc11
-rw-r--r--compiler/dex/mir_optimization_test.cc39
2 files changed, 32 insertions, 18 deletions
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 869c48f66..f69eea7fb 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -737,11 +737,9 @@ bool MIRGraph::EliminateNullChecksAndInferTypes(BasicBlock* bb) {
ArenaBitVector* ssa_regs_to_check = temp_bit_vector_;
if (do_nce) {
/*
- * Set initial state. Be conservative with catch
- * blocks and start with no assumptions about null check
- * status (except for "this").
+ * Set initial state. Catch blocks don't need any special treatment.
*/
- if ((bb->block_type == kEntryBlock) | bb->catch_entry) {
+ if (bb->block_type == kEntryBlock) {
ssa_regs_to_check->ClearAllBits();
// Assume all ins are objects.
for (uint16_t in_reg = cu_->num_dalvik_registers - cu_->num_ins;
@@ -1047,12 +1045,11 @@ bool MIRGraph::EliminateClassInitChecks(BasicBlock* bb) {
}
/*
- * Set initial state. Be conservative with catch
- * blocks and start with no assumptions about class init check status.
+ * Set initial state. Catch blocks don't need any special treatment.
*/
ArenaBitVector* classes_to_check = temp_bit_vector_;
DCHECK(classes_to_check != nullptr);
- if ((bb->block_type == kEntryBlock) | bb->catch_entry) {
+ if (bb->block_type == kEntryBlock) {
classes_to_check->SetInitialBits(temp_bit_vector_size_);
} else if (bb->predecessors->Size() == 1) {
BasicBlock* pred_bb = GetBasicBlock(bb->predecessors->Get(0));
diff --git a/compiler/dex/mir_optimization_test.cc b/compiler/dex/mir_optimization_test.cc
index 8c70b5c75..4a0cf5c78 100644
--- a/compiler/dex/mir_optimization_test.cc
+++ b/compiler/dex/mir_optimization_test.cc
@@ -373,30 +373,47 @@ TEST_F(ClassInitCheckEliminationTest, Catch) {
static const SFieldDef sfields[] = {
{ 0u, 1u, 0u, 0u },
{ 1u, 1u, 1u, 1u },
+ { 2u, 1u, 2u, 2u },
+ { 3u, 1u, 3u, 3u },
};
static const BBDef bbs[] = {
DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()),
DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()),
- DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(5)),
- DEF_BB(kDalvikByteCode, DEF_SUCC2(5, 4), DEF_PRED1(1)),
- DEF_BB(kDalvikByteCode, DEF_SUCC1(5), DEF_PRED1(3)), // Catch handler.
- DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED2(3, 4)),
+ DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(6)),
+ DEF_BB(kDalvikByteCode, DEF_SUCC1(4), DEF_PRED1(1)), // The top.
+ DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)), // The throwing insn.
+ DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)), // Catch handler.
+ DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED2(4, 5)), // The merged block.
};
static const MIRDef mirs[] = {
- DEF_MIR(Instruction::SGET, 3u, 0u),
- DEF_MIR(Instruction::SGET, 3u, 1u),
- DEF_MIR(Instruction::SGET, 4u, 1u),
- DEF_MIR(Instruction::SGET, 5u, 0u), // Not eliminated.
- DEF_MIR(Instruction::SGET, 5u, 1u), // Eliminated.
+ DEF_MIR(Instruction::SGET, 3u, 0u), // Before the exception edge.
+ DEF_MIR(Instruction::SGET, 3u, 1u), // Before the exception edge.
+ DEF_MIR(Instruction::SGET, 4u, 2u), // After the exception edge.
+ DEF_MIR(Instruction::SGET, 4u, 3u), // After the exception edge.
+ DEF_MIR(Instruction::SGET, 5u, 0u), // In catch handler; class init check eliminated.
+ DEF_MIR(Instruction::SGET, 5u, 2u), // In catch handler; class init check not eliminated.
+ DEF_MIR(Instruction::SGET, 6u, 0u), // Class init check eliminated.
+ DEF_MIR(Instruction::SGET, 6u, 1u), // Class init check eliminated.
+ DEF_MIR(Instruction::SGET, 6u, 2u), // Class init check eliminated.
+ DEF_MIR(Instruction::SGET, 6u, 3u), // Class init check not eliminated.
};
static const bool expected_ignore_clinit_check[] = {
- false, false, false, false, true
+ false, false, false, false, true, false, true, true, true, false
};
PrepareSFields(sfields);
PrepareBasicBlocks(bbs);
- BasicBlock* catch_handler = cu_.mir_graph->GetBasicBlock(4u);
+ BasicBlock* catch_handler = cu_.mir_graph->GetBasicBlock(5u);
catch_handler->catch_entry = true;
+ // Add successor block info to the check block.
+ BasicBlock* check_bb = cu_.mir_graph->GetBasicBlock(3u);
+ check_bb->successor_block_list_type = kCatch;
+ check_bb->successor_blocks = new (&cu_.arena) GrowableArray<SuccessorBlockInfo*>(
+ &cu_.arena, 2, kGrowableArraySuccessorBlocks);
+ SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
+ (cu_.arena.Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
+ successor_block_info->block = catch_handler->id;
+ check_bb->successor_blocks->Insert(successor_block_info);
PrepareMIRs(mirs);
PerformClassInitCheckElimination();
ASSERT_EQ(arraysize(expected_ignore_clinit_check), mir_count_);