Commit ba7d9e5f authored by Darius M's avatar Darius M Committed by V8 LUCI CQ

[turboshaft] port value numbering optimization

Bug: v8:12783
Change-Id: I5b7acf2445b0f898158448dde206a0cecdab6a80
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3764345Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82097}
parent 6fbe1bf2
...@@ -2870,6 +2870,7 @@ filegroup( ...@@ -2870,6 +2870,7 @@ filegroup(
"src/compiler/turboshaft/recreate-schedule.cc", "src/compiler/turboshaft/recreate-schedule.cc",
"src/compiler/turboshaft/recreate-schedule.h", "src/compiler/turboshaft/recreate-schedule.h",
"src/compiler/turboshaft/sidetable.h", "src/compiler/turboshaft/sidetable.h",
"src/compiler/turboshaft/value-numbering-assembler.h",
"src/compiler/type-cache.cc", "src/compiler/type-cache.cc",
"src/compiler/type-cache.h", "src/compiler/type-cache.h",
"src/compiler/type-narrowing-reducer.cc", "src/compiler/type-narrowing-reducer.cc",
......
...@@ -2985,6 +2985,7 @@ v8_header_set("v8_internal_headers") { ...@@ -2985,6 +2985,7 @@ v8_header_set("v8_internal_headers") {
"src/compiler/turboshaft/optimization-phase.h", "src/compiler/turboshaft/optimization-phase.h",
"src/compiler/turboshaft/recreate-schedule.h", "src/compiler/turboshaft/recreate-schedule.h",
"src/compiler/turboshaft/sidetable.h", "src/compiler/turboshaft/sidetable.h",
"src/compiler/turboshaft/value-numbering-assembler.h",
"src/compiler/type-cache.h", "src/compiler/type-cache.h",
"src/compiler/type-narrowing-reducer.h", "src/compiler/type-narrowing-reducer.h",
"src/compiler/typed-optimization.h", "src/compiler/typed-optimization.h",
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
#include "src/compiler/turboshaft/graph.h" #include "src/compiler/turboshaft/graph.h"
#include "src/compiler/turboshaft/optimization-phase.h" #include "src/compiler/turboshaft/optimization-phase.h"
#include "src/compiler/turboshaft/recreate-schedule.h" #include "src/compiler/turboshaft/recreate-schedule.h"
#include "src/compiler/turboshaft/value-numbering-assembler.h"
#include "src/compiler/type-narrowing-reducer.h" #include "src/compiler/type-narrowing-reducer.h"
#include "src/compiler/typed-optimization.h" #include "src/compiler/typed-optimization.h"
#include "src/compiler/typer.h" #include "src/compiler/typer.h"
...@@ -2045,9 +2046,10 @@ struct OptimizeTurboshaftPhase { ...@@ -2045,9 +2046,10 @@ struct OptimizeTurboshaftPhase {
DECL_PIPELINE_PHASE_CONSTANTS(OptimizeTurboshaft) DECL_PIPELINE_PHASE_CONSTANTS(OptimizeTurboshaft)
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
turboshaft::OptimizationPhase< turboshaft::OptimizationPhase<turboshaft::LivenessAnalyzer,
turboshaft::LivenessAnalyzer, turboshaft::ValueNumberingAssembler>::
turboshaft::Assembler>::Run(&data->turboshaft_graph(), temp_zone); Run(&data->turboshaft_graph(), temp_zone,
turboshaft::VisitOrder::kDominator);
} }
}; };
......
...@@ -208,6 +208,9 @@ class Assembler ...@@ -208,6 +208,9 @@ class Assembler
public: public:
Block* NewBlock(Block::Kind kind) { return graph_.NewBlock(kind); } Block* NewBlock(Block::Kind kind) { return graph_.NewBlock(kind); }
void EnterBlock(const Block& block) { USE(block); }
void ExitBlock(const Block& block) { USE(block); }
V8_INLINE bool Bind(Block* block) { V8_INLINE bool Bind(Block* block) {
if (!graph().Add(block)) return false; if (!graph().Add(block)) return false;
DCHECK_NULL(current_block_); DCHECK_NULL(current_block_);
......
...@@ -231,6 +231,8 @@ class RandomAccessStackDominatorNode ...@@ -231,6 +231,8 @@ class RandomAccessStackDominatorNode
// Returns the lowest common dominator of {this} and {other}. // Returns the lowest common dominator of {this} and {other}.
Derived* GetCommonDominator(RandomAccessStackDominatorNode<Derived>* other); Derived* GetCommonDominator(RandomAccessStackDominatorNode<Derived>* other);
int Depth() const { return len_; }
private: private:
friend class Graph; friend class Graph;
friend class DominatorForwardTreeNode<Derived>; friend class DominatorForwardTreeNode<Derived>;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef V8_COMPILER_TURBOSHAFT_OPERATIONS_H_ #ifndef V8_COMPILER_TURBOSHAFT_OPERATIONS_H_
#define V8_COMPILER_TURBOSHAFT_OPERATIONS_H_ #define V8_COMPILER_TURBOSHAFT_OPERATIONS_H_
#include <cmath>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <limits> #include <limits>
...@@ -200,6 +201,10 @@ struct OpProperties { ...@@ -200,6 +201,10 @@ struct OpProperties {
!(can_read || can_write || can_abort || is_block_terminator); !(can_read || can_write || can_abort || is_block_terminator);
const bool is_required_when_unused = const bool is_required_when_unused =
can_write || can_abort || is_block_terminator; can_write || can_abort || is_block_terminator;
// Nodes that don't read, write and aren't block terminators can be eliminated
// via value numbering.
const bool can_be_eliminated =
!(can_read || can_write || is_block_terminator);
constexpr OpProperties(bool can_read, bool can_write, bool can_abort, constexpr OpProperties(bool can_read, bool can_write, bool can_abort,
bool is_block_terminator) bool is_block_terminator)
...@@ -1031,10 +1036,20 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> { ...@@ -1031,10 +1036,20 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
case Kind::kTaggedIndex: case Kind::kTaggedIndex:
return storage.integral == other.storage.integral; return storage.integral == other.storage.integral;
case Kind::kFloat32: case Kind::kFloat32:
return storage.float32 == other.storage.float32; // Using a bit_cast to uint32_t in order to return false when comparing
// +0 and -0.
return base::bit_cast<uint32_t>(storage.float32) ==
base::bit_cast<uint32_t>(other.storage.float32) ||
(std::isnan(storage.float32) &&
std::isnan(other.storage.float32));
case Kind::kFloat64: case Kind::kFloat64:
case Kind::kNumber: case Kind::kNumber:
return storage.float64 == other.storage.float64; // Using a bit_cast to uint64_t in order to return false when comparing
// +0 and -0.
return base::bit_cast<uint64_t>(storage.float64) ==
base::bit_cast<uint64_t>(other.storage.float64) ||
(std::isnan(storage.float64) &&
std::isnan(other.storage.float64));
case Kind::kExternal: case Kind::kExternal:
return storage.external.address() == other.storage.external.address(); return storage.external.address() == other.storage.external.address();
case Kind::kHeapObject: case Kind::kHeapObject:
......
...@@ -95,15 +95,16 @@ struct LivenessAnalyzer : AnalyzerBase { ...@@ -95,15 +95,16 @@ struct LivenessAnalyzer : AnalyzerBase {
} }
}; };
enum class VisitOrder { kAsEmitted, kDominator };
template <class Analyzer, class Assembler> template <class Analyzer, class Assembler>
class OptimizationPhase { class OptimizationPhase {
private: private:
struct Impl; struct Impl;
public: public:
enum class VisitOrder { kNatural, kDominator };
static void Run(Graph* input, Zone* phase_zone, static void Run(Graph* input, Zone* phase_zone,
VisitOrder visit_order = VisitOrder::kNatural) { VisitOrder visit_order = VisitOrder::kAsEmitted) {
Impl phase{*input, phase_zone, visit_order}; Impl phase{*input, phase_zone, visit_order};
if (FLAG_turboshaft_trace_reduction) { if (FLAG_turboshaft_trace_reduction) {
phase.template Run<true>(); phase.template Run<true>();
...@@ -111,8 +112,9 @@ class OptimizationPhase { ...@@ -111,8 +112,9 @@ class OptimizationPhase {
phase.template Run<false>(); phase.template Run<false>();
} }
} }
static void RunWithoutTracing(Graph* input, Zone* phase_zone, static void RunWithoutTracing(
VisitOrder visit_order = VisitOrder::kNatural) { Graph* input, Zone* phase_zone,
VisitOrder visit_order = VisitOrder::kAsEmitted) {
Impl phase{*input, phase_zone, visit_order}; Impl phase{*input, phase_zone, visit_order};
phase.template Run<false>(); phase.template Run<false>();
} }
...@@ -146,14 +148,14 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl { ...@@ -146,14 +148,14 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
if (visit_order == VisitOrder::kDominator) { if (visit_order == VisitOrder::kDominator) {
RunDominatorOrder<trace_reduction>(); RunDominatorOrder<trace_reduction>();
} else { } else {
RunNaturalOrder<trace_reduction>(); RunAsEmittedOrder<trace_reduction>();
} }
input_graph.SwapWithCompanion(); input_graph.SwapWithCompanion();
} }
template <bool trace_reduction> template <bool trace_reduction>
void RunNaturalOrder() { void RunAsEmittedOrder() {
for (const Block& input_block : input_graph.blocks()) { for (const Block& input_block : input_graph.blocks()) {
VisitBlock<trace_reduction>(input_block); VisitBlock<trace_reduction>(input_block);
} }
...@@ -179,12 +181,14 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl { ...@@ -179,12 +181,14 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
template <bool trace_reduction> template <bool trace_reduction>
void VisitBlock(const Block& input_block) { void VisitBlock(const Block& input_block) {
assembler.EnterBlock(input_block);
current_input_block = &input_block; current_input_block = &input_block;
if constexpr (trace_reduction) { if constexpr (trace_reduction) {
std::cout << PrintAsBlockHeader{input_block} << "\n"; std::cout << PrintAsBlockHeader{input_block} << "\n";
} }
if (!assembler.Bind(MapToNewGraph(input_block.index()))) { if (!assembler.Bind(MapToNewGraph(input_block.index()))) {
if constexpr (trace_reduction) TraceBlockUnreachable(); if constexpr (trace_reduction) TraceBlockUnreachable();
assembler.ExitBlock(input_block);
return; return;
} }
assembler.current_block()->SetDeferred(input_block.IsDeferred()); assembler.current_block()->SetDeferred(input_block.IsDeferred());
...@@ -226,6 +230,7 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl { ...@@ -226,6 +230,7 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
} }
op_mapping[index.id()] = new_index; op_mapping[index.id()] = new_index;
} }
assembler.ExitBlock(input_block);
if constexpr (trace_reduction) TraceBlockFinished(); if constexpr (trace_reduction) TraceBlockFinished();
} }
...@@ -306,7 +311,7 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl { ...@@ -306,7 +311,7 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
// need to skip phi inputs that belong to control predecessors that have no // need to skip phi inputs that belong to control predecessors that have no
// equivalent in the new graph. // equivalent in the new graph.
// When iterating the graph in kNatural order (ie, going through all of // When iterating the graph in kAsEmitted order (ie, going through all of
// the blocks in linear order), we assume that the order of control // the blocks in linear order), we assume that the order of control
// predecessors did not change. In kDominator order, the order of control // predecessors did not change. In kDominator order, the order of control
// predecessor might or might not change. // predecessor might or might not change.
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment