blob: fbd84448be34130f615ffe855e5f686f928ca5b9 [file]
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_COMPILER_OPTIMIZING_LOOP_INFORMATION_H_
#define ART_COMPILER_OPTIMIZING_LOOP_INFORMATION_H_
#include <iosfwd>
#include "base/macros.h"
#include "base/arena_bit_vector.h"
#include "base/arena_containers.h"
#include "base/arena_object.h"
#include "base/value_object.h"
#include "base/stl_util.h"
namespace art HIDDEN {
class HBasicBlock;
class HGraph;
class HInstruction;
class HSuspendCheck;
class HLoopInformation final : public ArenaObject<kArenaAllocLoopInfo> {
public:
HLoopInformation(HBasicBlock* header, HGraph* graph);
bool IsIrreducible() const { return irreducible_; }
bool ContainsIrreducibleLoop() const { return contains_irreducible_loop_; }
void Dump(std::ostream& os);
HBasicBlock* GetHeader() const {
return header_;
}
void SetHeader(HBasicBlock* block) {
header_ = block;
}
HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
void AddBackEdge(HBasicBlock* back_edge) {
back_edges_.push_back(back_edge);
}
void RemoveBackEdge(HBasicBlock* back_edge) {
RemoveElement(back_edges_, back_edge);
}
bool IsBackEdge(const HBasicBlock& block) const {
return ContainsElement(back_edges_, &block);
}
size_t NumberOfBackEdges() const {
return back_edges_.size();
}
HBasicBlock* GetPreHeader() const;
const ArenaVector<HBasicBlock*>& GetBackEdges() const {
return back_edges_;
}
void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
ReplaceElement(back_edges_, existing, new_back_edge);
}
// Finds blocks that are part of this loop.
void Populate();
// Updates blocks population of the loop and all of its outer' ones recursively after the
// population of the inner loop is updated.
void PopulateInnerLoopUpwards(HLoopInformation* inner_loop);
// Returns whether this loop information contains `block`.
// Note that this loop information *must* be populated before entering this function.
bool Contains(const HBasicBlock& block) const;
// Returns whether this loop information is an inner loop of `other`.
// Note that `other` *must* be populated before entering this function.
bool IsIn(const HLoopInformation& other) const;
// Returns true if instruction is not defined within this loop.
bool IsDefinedOutOfTheLoop(HInstruction* instruction) const;
const ArenaBitVector& GetBlockMask() const { return block_mask_; }
void Add(HBasicBlock* block);
void Remove(HBasicBlock* block);
void ClearAllBlocks() {
block_mask_.ClearAllBits();
}
bool HasBackEdgeNotDominatedByHeader() const;
bool IsPopulated() const {
return block_mask_.GetHighestBitSet() != -1;
}
bool DominatesAllBackEdges(HBasicBlock* block);
bool HasExitEdge() const;
// Resets back edge and blocks-in-loop data.
void ResetBasicBlockData() {
back_edges_.clear();
ClearAllBlocks();
}
auto GetBlocks() const; // In block id order.
auto GetBlocksPostOrder() const;
auto GetBlocksReversePostOrder() const;
private:
// Internal recursive implementation of `Populate`.
void PopulateRecursive(HBasicBlock* block,
const ArenaSafeMap<HBasicBlock*, ArenaSet<HBasicBlock*>>& blocks_in_catch);
void PopulateIrreducibleRecursive(
HBasicBlock* block,
ArenaBitVector* finalized,
const ArenaSafeMap<HBasicBlock*, ArenaSet<HBasicBlock*>>& blocks_in_catch);
// Set the loop information in the `block`. Overrides the `block`'s current
// loop information if it is an outer loop of the loop information `*this`.
void MarkInLoop(HBasicBlock* block);
HBasicBlock* header_;
HSuspendCheck* suspend_check_;
bool irreducible_;
bool contains_irreducible_loop_;
ArenaVector<HBasicBlock*> back_edges_;
ArenaBitVector block_mask_;
DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
};
// Iterates over the LoopInformation of all loops which contain 'block'
// from the innermost to the outermost.
class HLoopInformationOutwardIterator final : public ValueObject {
public:
explicit HLoopInformationOutwardIterator(const HBasicBlock& block);
bool Done() const { return current_ == nullptr; }
void Advance();
HLoopInformation* Current() const {
DCHECK(!Done());
return current_;
}
private:
HLoopInformation* current_;
DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
};
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_LOOP_INFORMATION_H_