summaryrefslogtreecommitdiff
path: root/compiler/optimizing/select_generator.cc
diff options
context:
space:
mode:
authorArtem Serov <artem.serov@linaro.org>2018-06-29 15:30:36 +0100
committerArtem Serov <artem.serov@linaro.org>2018-06-29 19:29:53 +0100
commit15f95b103731a4386c784ef3ca79c47e68e27719 (patch)
tree12a257e5889029543d960c5578c20d2600824bb0 /compiler/optimizing/select_generator.cc
parentb5271dd44a30f498689e503340d3c8d01bf31f07 (diff)
ART: Fix HSelectGenerator for instructions which can throw.
Make sure that HSelectGenerator doesn't hoist instructions which can throw. Currently this doesn't happen due to SideEffect::CanTriggerGC however this side effect is to be removed for some instructions. Test: select_generator_test. Test: test-art-host, test-art-target. Change-Id: I996f6cbdcee4987a36079d387a7b74b326881ab6
Diffstat (limited to 'compiler/optimizing/select_generator.cc')
-rw-r--r--compiler/optimizing/select_generator.cc12
1 files changed, 9 insertions, 3 deletions
diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc
index 0d0f7cc748..dcc7f77fc2 100644
--- a/compiler/optimizing/select_generator.cc
+++ b/compiler/optimizing/select_generator.cc
@@ -45,7 +45,9 @@ static bool IsSimpleBlock(HBasicBlock* block) {
HInstruction* instruction = it.Current();
if (instruction->IsControlFlow()) {
return instruction->IsGoto() || instruction->IsReturn();
- } else if (instruction->CanBeMoved() && !instruction->HasSideEffects()) {
+ } else if (instruction->CanBeMoved() &&
+ !instruction->HasSideEffects() &&
+ !instruction->CanThrow()) {
if (instruction->IsSelect() &&
instruction->AsSelect()->GetCondition()->GetBlock() == block) {
// Count one HCondition and HSelect in the same block as a single instruction.
@@ -119,10 +121,14 @@ bool HSelectGenerator::Run() {
// TODO(dbrazdil): This puts an instruction between If and its condition.
// Implement moving of conditions to first users if possible.
while (!true_block->IsSingleGoto() && !true_block->IsSingleReturn()) {
- true_block->GetFirstInstruction()->MoveBefore(if_instruction);
+ HInstruction* instr = true_block->GetFirstInstruction();
+ DCHECK(!instr->CanThrow());
+ instr->MoveBefore(if_instruction);
}
while (!false_block->IsSingleGoto() && !false_block->IsSingleReturn()) {
- false_block->GetFirstInstruction()->MoveBefore(if_instruction);
+ HInstruction* instr = false_block->GetFirstInstruction();
+ DCHECK(!instr->CanThrow());
+ instr->MoveBefore(if_instruction);
}
DCHECK(true_block->IsSingleGoto() || true_block->IsSingleReturn());
DCHECK(false_block->IsSingleGoto() || false_block->IsSingleReturn());