diff options
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r-- | compiler/optimizing/nodes.cc | 81 |
1 files changed, 49 insertions, 32 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 4f6565d315..dca612e6b7 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -287,39 +287,62 @@ bool HGraph::AnalyzeNaturalLoops() const { return true; } -void HGraph::AddConstant(HConstant* instruction) { - HInstruction* last_instruction = entry_block_->GetLastInstruction(); - if (last_instruction == nullptr || !last_instruction->IsControlFlow()) { - // Called from the builder. Insert at the end of the block. - entry_block_->AddInstruction(instruction); +void HGraph::InsertConstant(HConstant* constant) { + // New constants are inserted before the final control-flow instruction + // of the graph, or at its end if called from the graph builder. + if (entry_block_->EndsWithControlFlowInstruction()) { + entry_block_->InsertInstructionBefore(constant, entry_block_->GetLastInstruction()); } else { - // Entry block ends with control-flow. Insert before the last instruction. - entry_block_->InsertInstructionBefore(instruction, last_instruction); + entry_block_->AddInstruction(constant); } } HNullConstant* HGraph::GetNullConstant() { if (cached_null_constant_ == nullptr) { cached_null_constant_ = new (arena_) HNullConstant(); - AddConstant(cached_null_constant_); + InsertConstant(cached_null_constant_); } return cached_null_constant_; } -HIntConstant* HGraph::GetIntConstant0() { - if (cached_int_constant0_ == nullptr) { - cached_int_constant0_ = new (arena_) HIntConstant(0); - AddConstant(cached_int_constant0_); +template <class InstructionType, typename ValueType> +InstructionType* HGraph::CreateConstant(ValueType value, + ArenaSafeMap<ValueType, InstructionType*>* cache) { + // Try to find an existing constant of the given value. + InstructionType* constant = nullptr; + auto cached_constant = cache->find(value); + if (cached_constant != cache->end()) { + constant = cached_constant->second; } - return cached_int_constant0_; + + // If not found or previously deleted, create and cache a new instruction. + if (constant == nullptr || constant->GetBlock() == nullptr) { + constant = new (arena_) InstructionType(value); + cache->Overwrite(value, constant); + InsertConstant(constant); + } + return constant; } -HIntConstant* HGraph::GetIntConstant1() { - if (cached_int_constant1_ == nullptr) { - cached_int_constant1_ = new (arena_) HIntConstant(1); - AddConstant(cached_int_constant1_); +HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value) { + switch (type) { + case Primitive::Type::kPrimBoolean: + DCHECK(IsUint<1>(value)); + FALLTHROUGH_INTENDED; + case Primitive::Type::kPrimByte: + case Primitive::Type::kPrimChar: + case Primitive::Type::kPrimShort: + case Primitive::Type::kPrimInt: + DCHECK(IsInt(Primitive::ComponentSize(type) * kBitsPerByte, value)); + return GetIntConstant(static_cast<int32_t>(value)); + + case Primitive::Type::kPrimLong: + return GetLongConstant(value); + + default: + LOG(FATAL) << "Unsupported constant type"; + UNREACHABLE(); } - return cached_int_constant1_; } void HLoopInformation::Add(HBasicBlock* block) { @@ -676,7 +699,7 @@ void HGraphVisitor::VisitBasicBlock(HBasicBlock* block) { HConstant* HUnaryOperation::TryStaticEvaluation() const { if (GetInput()->IsIntConstant()) { int32_t value = Evaluate(GetInput()->AsIntConstant()->GetValue()); - return new(GetBlock()->GetGraph()->GetArena()) HIntConstant(value); + return GetBlock()->GetGraph()->GetIntConstant(value); } else if (GetInput()->IsLongConstant()) { // TODO: Implement static evaluation of long unary operations. // @@ -692,15 +715,15 @@ HConstant* HBinaryOperation::TryStaticEvaluation() const { if (GetLeft()->IsIntConstant() && GetRight()->IsIntConstant()) { int32_t value = Evaluate(GetLeft()->AsIntConstant()->GetValue(), GetRight()->AsIntConstant()->GetValue()); - return new(GetBlock()->GetGraph()->GetArena()) HIntConstant(value); + return GetBlock()->GetGraph()->GetIntConstant(value); } else if (GetLeft()->IsLongConstant() && GetRight()->IsLongConstant()) { int64_t value = Evaluate(GetLeft()->AsLongConstant()->GetValue(), GetRight()->AsLongConstant()->GetValue()); if (GetResultType() == Primitive::kPrimLong) { - return new(GetBlock()->GetGraph()->GetArena()) HLongConstant(value); + return GetBlock()->GetGraph()->GetLongConstant(value); } else { DCHECK_EQ(GetResultType(), Primitive::kPrimInt); - return new(GetBlock()->GetGraph()->GetArena()) HIntConstant(value); + return GetBlock()->GetGraph()->GetIntConstant(static_cast<int32_t>(value)); } } return nullptr; @@ -733,16 +756,6 @@ bool HCondition::IsBeforeWhenDisregardMoves(HIf* if_) const { return this == if_->GetPreviousDisregardingMoves(); } -HConstant* HConstant::NewConstant(ArenaAllocator* allocator, Primitive::Type type, int64_t val) { - if (type == Primitive::kPrimInt) { - DCHECK(IsInt<32>(val)); - return new (allocator) HIntConstant(val); - } else { - DCHECK_EQ(type, Primitive::kPrimLong); - return new (allocator) HLongConstant(val); - } -} - bool HInstruction::Equals(HInstruction* other) const { if (!InstructionTypeEquals(other)) return false; DCHECK_EQ(GetKind(), other->GetKind()); @@ -832,6 +845,10 @@ bool HBasicBlock::IsSingleGoto() const { && (loop_info == nullptr || !loop_info->IsBackEdge(*this)); } +bool HBasicBlock::EndsWithControlFlowInstruction() const { + return !GetInstructions().IsEmpty() && GetLastInstruction()->IsControlFlow(); +} + bool HBasicBlock::EndsWithIf() const { return !GetInstructions().IsEmpty() && GetLastInstruction()->IsIf(); } |