5#ifndef V8_COMPILER_TURBOSHAFT_DEAD_CODE_ELIMINATION_REDUCER_H_
6#define V8_COMPILER_TURBOSHAFT_DEAD_CODE_ELIMINATION_REDUCER_H_
125 switch (state.kind) {
127 return stream <<
"NotEliminatable";
129 return stream <<
"Block(" << state.block <<
")";
131 return stream <<
"Unreachable";
136 if (lhs.
kind != rhs.
kind)
return false;
145 return !(lhs == rhs);
163 return static_cast<Liveness>(lhs | rhs);
171 return stream <<
"Dead";
173 return stream <<
"Live";
188 template <
bool trace_analysis>
189 std::pair<FixedOpIndexSidetable<OperationState::Liveness>,
192 if constexpr (trace_analysis) {
193 std::cout <<
"===== Running Dead Code Analysis =====\n";
196 unprocessed_count > 0;) {
204 if constexpr (trace_analysis) {
205 std::cout <<
"===== Results =====\n== Operation State ==\n";
210 << std::setw(3) << index.id() <<
": " <<
graph_.
Get(index)
215 std::cout <<
"== Rewritable Branches ==\n";
218 std::cout <<
" " << std::setw(3) << branch_id <<
": Branch ==> Goto "
219 << target.id() <<
"\n";
221 std::cout <<
"==========\n";
227 template <
bool trace_analysis>
229 if constexpr (trace_analysis) {
231 <<
":\n==========\nEXIT CONTROL STATE\n";
235 for (
size_t i = 0;
i < successors.
size(); ++
i) {
237 if constexpr (trace_analysis) {
238 std::cout <<
" Successor " << successors[
i]->index() <<
": " <<
r
243 if constexpr (trace_analysis)
244 std::cout <<
"Combined: " << control_state <<
"\n";
250 if constexpr (trace_analysis) std::cout <<
"OPERATION STATE\n";
252 bool has_live_phis =
false;
253 for (
auto it = op_range.end(); it != op_range.begin();) {
257 if constexpr (trace_analysis) std::cout << index <<
":" << op <<
"\n";
286 if (block.IsLoop()) {
293 if constexpr (trace_analysis) {
295 <<
"Operation state has changed. Need to revisit loop.\n";
301 std::max(*unprocessed_count, backedge->
index().
id() + 1);
322 if constexpr (trace_analysis) {
323 std::cout <<
" " << op_state <<
" <== " <<
liveness_[
index] <<
"\n";
327 if constexpr (trace_analysis) {
328 if (op.
input_count > 0) std::cout <<
" Updating inputs:\n";
332 auto new_input_state =
334 if constexpr (trace_analysis) {
335 std::cout <<
" " << input <<
": " << new_input_state
336 <<
" <== " << old_input_state <<
" || " << op_state <<
"\n";
345 if constexpr (trace_analysis) {
346 std::cout <<
"Block has live operations. New control state: "
353 if constexpr (trace_analysis) {
354 std::cout <<
"ENTRY CONTROL STATE\nAfter operations: " << control_state
360 if (block.IsMerge()) {
361 if (!has_live_phis) {
364 if constexpr (trace_analysis) {
366 <<
"Block is loop or merge and has no live phi operations.\n";
368 }
else if constexpr (trace_analysis) {
369 std::cout <<
"Block is loop or merge and has no live phi "
370 "operations.\nControl state already has a goto block: "
371 << control_state <<
"\n";
374 }
else if (block.IsLoop()) {
380 if constexpr (trace_analysis) {
381 std::cout <<
"Block is loop header. Resetting control state: "
382 << control_state <<
"\n";
386 if constexpr (trace_analysis) {
387 std::cout <<
"Control state has changed. Need to revisit loop.\n";
394 std::max(*unprocessed_count, backedge->
index().
id() + 1);
398 if constexpr (trace_analysis) {
399 std::cout <<
"Final: " << control_state <<
"\n";
434 constexpr bool trace_analysis =
false;
442 return Next::ReduceInputGraphBranch(ig_index, branch);
447 return Next::ReduceInputGraphGoto(ig_index, gto);
450 template <
typename Op,
typename Continuation>
455 return Continuation{
this}.ReduceInputGraph(ig_index, op);
464 Asm().Goto(Asm().MapToNewGraph(&Asm().input_graph().
Get(*goto_target)));
469 std::optional<FixedOpIndexSidetable<OperationState::Liveness>>
liveness_;
471 Asm().phase_zone(), &Asm().input_graph()};
#define REDUCE_INPUT_GRAPH(operation)
static constexpr BlockIndex Invalid()
Block * LastPredecessor() const
bool is_leaf_function() const
FixedBlockSidetable< ControlState > entry_control_state_
SparseOpIndexSideTable< BlockIndex > rewritable_branch_targets_
std::pair< FixedOpIndexSidetable< OperationState::Liveness >, SparseOpIndexSideTable< BlockIndex > > Run()
FixedOpIndexSidetable< OperationState::Liveness > liveness_
void ProcessBlock(const Block &block, uint32_t *unprocessed_count)
DeadCodeAnalysis(Graph &graph, Zone *phase_zone)
bool IsLeafFunction() const
OpIndex ReduceInputGraphOperation(OpIndex ig_index, const Op &op)
bool TryRewriteBranch(OpIndex index)
DeadCodeAnalysis analyzer_
SparseOpIndexSideTable< BlockIndex > branch_rewrite_targets_
V< None > REDUCE_INPUT_GRAPH Goto(V< None > ig_index, const GotoOp >o)
V< None > REDUCE_INPUT_GRAPH Branch(V< None > ig_index, const BranchOp &branch)
bool CanAutoInlineBlocksWithSinglePredecessor() const
std::optional< FixedOpIndexSidetable< OperationState::Liveness > > liveness_
uint32_t block_count() const
base::iterator_range< OpIndexIterator > OperationIndices(const Block &block) const
base::iterator_range< base::DerefPtrIterator< Block > > blocks()
V8_INLINE const Operation & Get(OpIndex i) const
static constexpr OpIndex Invalid()
#define TURBOSHAFT_REDUCER_BOILERPLATE(Name)
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
bool operator==(const ControlState &lhs, const ControlState &rhs)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
base::SmallVector< Block *, 4 > SuccessorBlocks(const Block &block, const Graph &graph)
bool operator!=(const ControlState &lhs, const ControlState &rhs)
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
ControlState(Kind kind, BlockIndex block=BlockIndex::Invalid())
static ControlState Block(BlockIndex block)
static ControlState Unreachable()
static ControlState LeastUpperBound(const ControlState &lhs, const ControlState &rhs)
static ControlState NotEliminatable()
static Liveness LeastUpperBound(Liveness lhs, Liveness rhs)
bool IsRequiredWhenUnused() const
const uint16_t input_count
base::Vector< const OpIndex > inputs() const
underlying_operation_t< Op > & Cast()
static constexpr size_t kLoopPhiBackEdgeIndex