diff options
author | Calin Juravle <calin@google.com> | 2014-11-04 16:40:20 +0000 |
---|---|---|
committer | Calin Juravle <calin@google.com> | 2014-11-06 14:42:58 +0000 |
commit | d0d4852847432368b090c184d6639e573538dccf (patch) | |
tree | 47e31fe860ff1c3ace2f3f5945aa69689d42d998 /compiler/optimizing/builder.cc | |
parent | a88b7b93e28ea86969dd3ec6a6bf6929d697fc31 (diff) | |
download | art-d0d4852847432368b090c184d6639e573538dccf.tar.gz art-d0d4852847432368b090c184d6639e573538dccf.tar.bz2 art-d0d4852847432368b090c184d6639e573538dccf.zip |
[optimizing compiler] Add div-int and exception handling.
- for backends: arm, x86, x86_64
- fixed a register allocator bug: the request for a fixed register for
the first input was ignored if the output was kSameAsFirstInput
- added divide by zero exception
- more tests
- shuffle around some code in the builder to reduce the number of lines
of code for a single function.
Change-Id: Id3a515e02bfbc66cd9d16cb9746f7551bdab3d42
Diffstat (limited to 'compiler/optimizing/builder.cc')
-rw-r--r-- | compiler/optimizing/builder.cc | 143 |
1 files changed, 92 insertions, 51 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 4ce23d725..d30f3e38c 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -537,6 +537,27 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, return true; } +void HGraphBuilder::BuildCheckedDiv(const Instruction& instruction, + uint32_t dex_offset, + Primitive::Type type, + bool second_is_lit) { + DCHECK(type == Primitive::kPrimInt); + + HInstruction* first = LoadLocal(instruction.VRegB(), type); + HInstruction* second = second_is_lit + ? GetIntConstant(instruction.VRegC()) + : LoadLocal(instruction.VRegC(), type); + if (!second->IsIntConstant() || (second->AsIntConstant()->GetValue() == 0)) { + second = new (arena_) HDivZeroCheck(second, dex_offset); + Temporaries temps(graph_, 1); + current_block_->AddInstruction(second); + temps.Add(current_block_->GetLastInstruction()); + } + + current_block_->AddInstruction(new (arena_) HDiv(type, first, second)); + UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); +} + void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, uint32_t dex_offset, bool is_put, @@ -617,6 +638,60 @@ void HGraphBuilder::BuildFillArrayData(HInstruction* object, } } +void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_offset) { + Temporaries temps(graph_, 1); + HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot); + HNullCheck* null_check = new (arena_) HNullCheck(array, dex_offset); + current_block_->AddInstruction(null_check); + temps.Add(null_check); + + HInstruction* length = new (arena_) HArrayLength(null_check); + current_block_->AddInstruction(length); + + int32_t payload_offset = instruction.VRegB_31t() + dex_offset; + const Instruction::ArrayDataPayload* payload = + reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset); + const uint8_t* data = payload->data; + uint32_t element_count = payload->element_count; + + // Implementation of this DEX instruction seems to be that the bounds check is + // done before doing any stores. + HInstruction* last_index = GetIntConstant(payload->element_count - 1); + current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_offset)); + + switch (payload->element_width) { + case 1: + BuildFillArrayData(null_check, + reinterpret_cast<const int8_t*>(data), + element_count, + Primitive::kPrimByte, + dex_offset); + break; + case 2: + BuildFillArrayData(null_check, + reinterpret_cast<const int16_t*>(data), + element_count, + Primitive::kPrimShort, + dex_offset); + break; + case 4: + BuildFillArrayData(null_check, + reinterpret_cast<const int32_t*>(data), + element_count, + Primitive::kPrimInt, + dex_offset); + break; + case 8: + BuildFillWideArrayData(null_check, + reinterpret_cast<const int64_t*>(data), + element_count, + dex_offset); + break; + default: + LOG(FATAL) << "Unknown element width for " << payload->element_width; + } +} + void HGraphBuilder::BuildFillWideArrayData(HInstruction* object, const int64_t* data, uint32_t element_count, @@ -901,6 +976,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::DIV_INT: { + BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, false); + break; + } + case Instruction::DIV_FLOAT: { Binop_23x<HDiv>(instruction, Primitive::kPrimFloat); break; @@ -966,6 +1046,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::DIV_INT_2ADDR: { + BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, false); + break; + } + case Instruction::DIV_FLOAT_2ADDR: { Binop_12x<HDiv>(instruction, Primitive::kPrimFloat); break; @@ -1006,6 +1091,12 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::DIV_INT_LIT16: + case Instruction::DIV_INT_LIT8: { + BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, true); + break; + } + case Instruction::NEW_INSTANCE: { current_block_->AddInstruction( new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c())); @@ -1040,57 +1131,7 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 } case Instruction::FILL_ARRAY_DATA: { - Temporaries temps(graph_, 1); - HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot); - HNullCheck* null_check = new (arena_) HNullCheck(array, dex_offset); - current_block_->AddInstruction(null_check); - temps.Add(null_check); - - HInstruction* length = new (arena_) HArrayLength(null_check); - current_block_->AddInstruction(length); - - int32_t payload_offset = instruction.VRegB_31t() + dex_offset; - const Instruction::ArrayDataPayload* payload = - reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset); - const uint8_t* data = payload->data; - uint32_t element_count = payload->element_count; - - // Implementation of this DEX instruction seems to be that the bounds check is - // done before doing any stores. - HInstruction* last_index = GetIntConstant(payload->element_count - 1); - current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_offset)); - - switch (payload->element_width) { - case 1: - BuildFillArrayData(null_check, - reinterpret_cast<const int8_t*>(data), - element_count, - Primitive::kPrimByte, - dex_offset); - break; - case 2: - BuildFillArrayData(null_check, - reinterpret_cast<const int16_t*>(data), - element_count, - Primitive::kPrimShort, - dex_offset); - break; - case 4: - BuildFillArrayData(null_check, - reinterpret_cast<const int32_t*>(data), - element_count, - Primitive::kPrimInt, - dex_offset); - break; - case 8: - BuildFillWideArrayData(null_check, - reinterpret_cast<const int64_t*>(data), - element_count, - dex_offset); - break; - default: - LOG(FATAL) << "Unknown element width for " << payload->element_width; - } + BuildFillArrayData(instruction, dex_offset); break; } |