summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/nodes.cc
diff options
context:
space:
mode:
authorDavid Brazdil <dbrazdil@google.com>2015-03-24 10:51:52 +0000
committerDavid Brazdil <dbrazdil@google.com>2015-03-26 14:10:03 +0000
commit8d5b8b295930aaa43255c4f0b74ece3ee8b43a47 (patch)
treec26fc49bbc74615e7f0b9657aaf3757a8282d7a9 /compiler/optimizing/nodes.cc
parentc8924c6ea9e83ba3832dd5551df38ab06f4aaca9 (diff)
downloadandroid_art-8d5b8b295930aaa43255c4f0b74ece3ee8b43a47.tar.gz
android_art-8d5b8b295930aaa43255c4f0b74ece3ee8b43a47.tar.bz2
android_art-8d5b8b295930aaa43255c4f0b74ece3ee8b43a47.zip
ART: Force constants into the entry block
Optimizations such as GVN and BCE make the assumption that all constants are located in the entry block of the CFG, but not all passes adhere to this rule. This patch makes constructors of constants private and only accessible to friend classes - HGraph for int/long constants and SsaBuilder for float/double - which ensure that they are placed correctly and not duplicated. Note that the ArenaAllocatorAdapter was modified to not increment the ArenaAllocator's internal reference counter in order to allow for use of ArenaSafeMap inside an arena-allocated objects. Because their destructor is not called, the counter does not get decremented. Change-Id: I36a4fa29ae34fb905cdefd482ccbf386cff14166
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r--compiler/optimizing/nodes.cc81
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();
}