diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-04-27 08:53:46 +0000 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2015-04-27 15:05:20 +0100 |
commit | f213e05cef6d38166cfe0cce8f3b0a53225a1b39 (patch) | |
tree | 2fd9573056062ae085f84f1b63b8ec3298927da1 /compiler/optimizing | |
parent | 76bf84a196576f902a76a1165516a49dac15856f (diff) | |
download | art-f213e05cef6d38166cfe0cce8f3b0a53225a1b39.zip art-f213e05cef6d38166cfe0cce8f3b0a53225a1b39.tar.gz art-f213e05cef6d38166cfe0cce8f3b0a53225a1b39.tar.bz2 |
Add support for caching float and double constants.
Change-Id: Ib5205bad1006bc5e3c9cc86bc82a6b4b1ce9bef9
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/nodes.cc | 38 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 61 | ||||
-rw-r--r-- | compiler/optimizing/ssa_builder.cc | 2 |
3 files changed, 67 insertions, 34 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index ca470f4..c172512 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -303,25 +303,6 @@ HNullConstant* HGraph::GetNullConstant() { return cached_null_constant_; } -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; - } - - // 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; -} - HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value) { switch (type) { case Primitive::Type::kPrimBoolean: @@ -343,6 +324,18 @@ HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value) { } } +void HGraph::CacheFloatConstant(HFloatConstant* constant) { + int32_t value = bit_cast<int32_t, float>(constant->GetValue()); + DCHECK(cached_float_constants_.find(value) == cached_float_constants_.end()); + cached_float_constants_.Overwrite(value, constant); +} + +void HGraph::CacheDoubleConstant(HDoubleConstant* constant) { + int64_t value = bit_cast<int64_t, double>(constant->GetValue()); + DCHECK(cached_double_constants_.find(value) == cached_double_constants_.end()); + cached_double_constants_.Overwrite(value, constant); +} + void HLoopInformation::Add(HBasicBlock* block) { blocks_.SetBit(block->GetBlockId()); } @@ -1303,9 +1296,10 @@ void HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { current->ReplaceWith(outer_graph->GetIntConstant(current->AsIntConstant()->GetValue())); } else if (current->IsLongConstant()) { current->ReplaceWith(outer_graph->GetLongConstant(current->AsLongConstant()->GetValue())); - } else if (current->IsFloatConstant() || current->IsDoubleConstant()) { - // TODO: Don't duplicate floating-point constants. - current->MoveBefore(outer_graph->GetEntryBlock()->GetLastInstruction()); + } else if (current->IsFloatConstant()) { + current->ReplaceWith(outer_graph->GetFloatConstant(current->AsFloatConstant()->GetValue())); + } else if (current->IsDoubleConstant()) { + current->ReplaceWith(outer_graph->GetDoubleConstant(current->AsDoubleConstant()->GetValue())); } else if (current->IsParameterValue()) { if (kIsDebugBuild && invoke->IsInvokeStaticOrDirect() diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index d970e38..8adc246 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -132,7 +132,9 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { current_instruction_id_(start_instruction_id), cached_null_constant_(nullptr), cached_int_constants_(std::less<int32_t>(), arena->Adapter()), - cached_long_constants_(std::less<int64_t>(), arena->Adapter()) {} + cached_float_constants_(std::less<int32_t>(), arena->Adapter()), + cached_long_constants_(std::less<int64_t>(), arena->Adapter()), + cached_double_constants_(std::less<int64_t>(), arena->Adapter()) {} ArenaAllocator* GetArena() const { return arena_; } const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; } @@ -241,8 +243,8 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { bool IsDebuggable() const { return debuggable_; } // Returns a constant of the given type and value. If it does not exist - // already, it is created and inserted into the graph. Only integral types - // are currently supported. + // already, it is created and inserted into the graph. This method is only for + // integral types. HConstant* GetConstant(Primitive::Type type, int64_t value); HNullConstant* GetNullConstant(); HIntConstant* GetIntConstant(int32_t value) { @@ -251,6 +253,12 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { HLongConstant* GetLongConstant(int64_t value) { return CreateConstant(value, &cached_long_constants_); } + HFloatConstant* GetFloatConstant(float value) { + return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_); + } + HDoubleConstant* GetDoubleConstant(double value) { + return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_); + } HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const; @@ -265,10 +273,34 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const; void RemoveDeadBlocks(const ArenaBitVector& visited); - template <class InstType, typename ValueType> - InstType* CreateConstant(ValueType value, ArenaSafeMap<ValueType, InstType*>* cache); + template <class InstructionType, typename ValueType> + InstructionType* 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; + } + + // 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; + } + void InsertConstant(HConstant* instruction); + // Cache a float constant into the graph. This method should only be + // called by the SsaBuilder when creating "equivalent" instructions. + void CacheFloatConstant(HFloatConstant* constant); + + // See CacheFloatConstant comment. + void CacheDoubleConstant(HDoubleConstant* constant); + ArenaAllocator* const arena_; // List of blocks in insertion order. @@ -306,11 +338,14 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { // The current id to assign to a newly added instruction. See HInstruction.id_. int32_t current_instruction_id_; - // Cached common constants often needed by optimization passes. + // Cached constants. HNullConstant* cached_null_constant_; ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_; + ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_; ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_; + ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_; + friend class SsaBuilder; // For caching constants. friend class SsaLivenessAnalysis; // For the linear order. ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1); DISALLOW_COPY_AND_ASSIGN(HGraph); @@ -2045,13 +2080,14 @@ class HFloatConstant : public HConstant { private: explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {} + explicit HFloatConstant(int32_t value) + : HConstant(Primitive::kPrimFloat), value_(bit_cast<float, int32_t>(value)) {} const float value_; - // Only the SsaBuilder can currently create floating-point constants. If we - // ever need to create them later in the pipeline, we will have to handle them - // the same way as integral constants. + // Only the SsaBuilder and HGraph can create floating-point constants. friend class SsaBuilder; + friend class HGraph; DISALLOW_COPY_AND_ASSIGN(HFloatConstant); }; @@ -2082,13 +2118,14 @@ class HDoubleConstant : public HConstant { private: explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {} + explicit HDoubleConstant(int64_t value) + : HConstant(Primitive::kPrimDouble), value_(bit_cast<double, int64_t>(value)) {} const double value_; - // Only the SsaBuilder can currently create floating-point constants. If we - // ever need to create them later in the pipeline, we will have to handle them - // the same way as integral constants. + // Only the SsaBuilder and HGraph can create floating-point constants. friend class SsaBuilder; + friend class HGraph; DISALLOW_COPY_AND_ASSIGN(HDoubleConstant); }; diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index 7a252af..b66e655 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -417,6 +417,7 @@ HFloatConstant* SsaBuilder::GetFloatEquivalent(HIntConstant* constant) { ArenaAllocator* allocator = graph->GetArena(); result = new (allocator) HFloatConstant(bit_cast<float, int32_t>(constant->GetValue())); constant->GetBlock()->InsertInstructionBefore(result, constant->GetNext()); + graph->CacheFloatConstant(result); } else { // If there is already a constant with the expected type, we know it is // the floating point equivalent of this constant. @@ -439,6 +440,7 @@ HDoubleConstant* SsaBuilder::GetDoubleEquivalent(HLongConstant* constant) { ArenaAllocator* allocator = graph->GetArena(); result = new (allocator) HDoubleConstant(bit_cast<double, int64_t>(constant->GetValue())); constant->GetBlock()->InsertInstructionBefore(result, constant->GetNext()); + graph->CacheDoubleConstant(result); } else { // If there is already a constant with the expected type, we know it is // the floating point equivalent of this constant. |