Commit 010e15a7 authored by Danylo Boiko's avatar Danylo Boiko Committed by V8 LUCI CQ

[turboshaft] Generating JSON from Turboshaft graphs

Change-Id: If1414fd2c01816461983d9bcebeaef5785ef355a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3669694Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80809}
parent 21172788
...@@ -2827,6 +2827,8 @@ filegroup( ...@@ -2827,6 +2827,8 @@ filegroup(
"src/compiler/turboshaft/graph-builder.h", "src/compiler/turboshaft/graph-builder.h",
"src/compiler/turboshaft/graph.cc", "src/compiler/turboshaft/graph.cc",
"src/compiler/turboshaft/graph.h", "src/compiler/turboshaft/graph.h",
"src/compiler/turboshaft/graph-visualizer.cc",
"src/compiler/turboshaft/graph-visualizer.h",
"src/compiler/turboshaft/operations.cc", "src/compiler/turboshaft/operations.cc",
"src/compiler/turboshaft/operations.h", "src/compiler/turboshaft/operations.h",
"src/compiler/turboshaft/optimization-phase.cc", "src/compiler/turboshaft/optimization-phase.cc",
......
...@@ -2909,6 +2909,7 @@ v8_header_set("v8_internal_headers") { ...@@ -2909,6 +2909,7 @@ v8_header_set("v8_internal_headers") {
"src/compiler/turboshaft/assembler.h", "src/compiler/turboshaft/assembler.h",
"src/compiler/turboshaft/deopt-data.h", "src/compiler/turboshaft/deopt-data.h",
"src/compiler/turboshaft/graph-builder.h", "src/compiler/turboshaft/graph-builder.h",
"src/compiler/turboshaft/graph-visualizer.h",
"src/compiler/turboshaft/graph.h", "src/compiler/turboshaft/graph.h",
"src/compiler/turboshaft/operations.h", "src/compiler/turboshaft/operations.h",
"src/compiler/turboshaft/optimization-phase.h", "src/compiler/turboshaft/optimization-phase.h",
...@@ -4117,6 +4118,7 @@ v8_source_set("v8_turboshaft") { ...@@ -4117,6 +4118,7 @@ v8_source_set("v8_turboshaft") {
sources = [ sources = [
"src/compiler/turboshaft/graph-builder.cc", "src/compiler/turboshaft/graph-builder.cc",
"src/compiler/turboshaft/graph-visualizer.cc",
"src/compiler/turboshaft/graph.cc", "src/compiler/turboshaft/graph.cc",
"src/compiler/turboshaft/operations.cc", "src/compiler/turboshaft/operations.cc",
"src/compiler/turboshaft/optimization-phase.cc", "src/compiler/turboshaft/optimization-phase.cc",
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#include "src/compiler/store-store-elimination.h" #include "src/compiler/store-store-elimination.h"
#include "src/compiler/turboshaft/assembler.h" #include "src/compiler/turboshaft/assembler.h"
#include "src/compiler/turboshaft/graph-builder.h" #include "src/compiler/turboshaft/graph-builder.h"
#include "src/compiler/turboshaft/graph-visualizer.h"
#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"
...@@ -965,15 +966,12 @@ void PrintCode(Isolate* isolate, Handle<Code> code, ...@@ -965,15 +966,12 @@ void PrintCode(Isolate* isolate, Handle<Code> code,
#endif // ENABLE_DISASSEMBLER #endif // ENABLE_DISASSEMBLER
} }
void TraceScheduleAndVerify(OptimizedCompilationInfo* info, PipelineData* data, void TraceSchedule(OptimizedCompilationInfo* info, PipelineData* data,
Schedule* schedule, const char* phase_name) { Schedule* schedule, const char* phase_name) {
RCS_SCOPE(data->runtime_call_stats(),
RuntimeCallCounterId::kOptimizeTraceScheduleAndVerify,
RuntimeCallStats::kThreadSpecific);
TRACE_EVENT0(PipelineStatistics::kTraceCategory, "V8.TraceScheduleAndVerify");
if (info->trace_turbo_json()) { if (info->trace_turbo_json()) {
UnparkedScopeIfNeeded scope(data->broker()); UnparkedScopeIfNeeded scope(data->broker());
AllowHandleDereference allow_deref; AllowHandleDereference allow_deref;
TurboJsonFile json_of(info, std::ios_base::app); TurboJsonFile json_of(info, std::ios_base::app);
json_of << "{\"name\":\"" << phase_name << "\",\"type\":\"schedule\"" json_of << "{\"name\":\"" << phase_name << "\",\"type\":\"schedule\""
<< ",\"data\":\""; << ",\"data\":\"";
...@@ -985,14 +983,26 @@ void TraceScheduleAndVerify(OptimizedCompilationInfo* info, PipelineData* data, ...@@ -985,14 +983,26 @@ void TraceScheduleAndVerify(OptimizedCompilationInfo* info, PipelineData* data,
} }
json_of << "\"},\n"; json_of << "\"},\n";
} }
if (info->trace_turbo_graph() || FLAG_trace_turbo_scheduler) { if (info->trace_turbo_graph() || FLAG_trace_turbo_scheduler) {
UnparkedScopeIfNeeded scope(data->broker()); UnparkedScopeIfNeeded scope(data->broker());
AllowHandleDereference allow_deref; AllowHandleDereference allow_deref;
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer()); CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
tracing_scope.stream() tracing_scope.stream()
<< "-- Schedule --------------------------------------\n" << "----- " << phase_name << " -----\n"
<< *schedule; << *schedule;
} }
}
void TraceScheduleAndVerify(OptimizedCompilationInfo* info, PipelineData* data,
Schedule* schedule, const char* phase_name) {
RCS_SCOPE(data->runtime_call_stats(),
RuntimeCallCounterId::kOptimizeTraceScheduleAndVerify,
RuntimeCallStats::kThreadSpecific);
TRACE_EVENT0(PipelineStatistics::kTraceCategory, "V8.TraceScheduleAndVerify");
TraceSchedule(info, data, schedule, phase_name);
if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule); if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule);
} }
...@@ -2493,7 +2503,6 @@ struct FinalizeCodePhase { ...@@ -2493,7 +2503,6 @@ struct FinalizeCodePhase {
} }
}; };
struct PrintGraphPhase { struct PrintGraphPhase {
DECL_PIPELINE_PHASE_CONSTANTS(PrintGraph) DECL_PIPELINE_PHASE_CONSTANTS(PrintGraph)
...@@ -2524,19 +2533,44 @@ struct PrintGraphPhase { ...@@ -2524,19 +2533,44 @@ struct PrintGraphPhase {
AllowHandleDereference allow_deref; AllowHandleDereference allow_deref;
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer()); CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
tracing_scope.stream() tracing_scope.stream()
<< "-- Graph after " << phase << " -- " << std::endl << "----- Graph after " << phase << " ----- " << std::endl
<< AsScheduledGraph(schedule); << AsScheduledGraph(schedule);
} else if (info->trace_turbo_graph()) { // Simple textual RPO. } else if (info->trace_turbo_graph()) { // Simple textual RPO.
UnparkedScopeIfNeeded scope(data->broker()); UnparkedScopeIfNeeded scope(data->broker());
AllowHandleDereference allow_deref; AllowHandleDereference allow_deref;
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer()); CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
tracing_scope.stream() tracing_scope.stream()
<< "-- Graph after " << phase << " -- " << std::endl << "----- Graph after " << phase << " ----- " << std::endl
<< AsRPO(*graph); << AsRPO(*graph);
} }
} }
}; };
struct PrintTurboshaftGraphPhase {
DECL_PIPELINE_PHASE_CONSTANTS(PrintTurboshaftGraph)
void Run(PipelineData* data, Zone* temp_zone, const char* phase) {
if (data->info()->trace_turbo_json()) {
UnparkedScopeIfNeeded scope(data->broker());
AllowHandleDereference allow_deref;
TurboJsonFile json_of(data->info(), std::ios_base::app);
json_of << "{\"name\":\"" << phase << "\",\"type\":\"turboshaft_graph\",\"data\":"
<< AsJSON(data->turboshaft_graph(), temp_zone)
<< "},\n";
}
if (data->info()->trace_turbo_graph()) {
UnparkedScopeIfNeeded scope(data->broker());
AllowHandleDereference allow_deref;
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
tracing_scope.stream()
<< "\n----- " << phase << " -----\n"
<< data->turboshaft_graph();
}
}
};
struct VerifyGraphPhase { struct VerifyGraphPhase {
DECL_PIPELINE_PHASE_CONSTANTS(VerifyGraph) DECL_PIPELINE_PHASE_CONSTANTS(VerifyGraph)
...@@ -2883,26 +2917,14 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) { ...@@ -2883,26 +2917,14 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
if (FLAG_turboshaft) { if (FLAG_turboshaft) {
Run<BuildTurboshaftPhase>(); Run<BuildTurboshaftPhase>();
if (data->info()->trace_turbo_graph()) { Run<PrintTurboshaftGraphPhase>(BuildTurboshaftPhase::phase_name());
UnparkedScopeIfNeeded scope(data->broker());
AllowHandleDereference allow_deref;
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
tracing_scope.stream()
<< "\n-- Turboshaft Graph ----------------------------\n"
<< data->turboshaft_graph();
}
Run<OptimizeTurboshaftPhase>(); Run<OptimizeTurboshaftPhase>();
Run<PrintTurboshaftGraphPhase>(OptimizeTurboshaftPhase::phase_name());
Run<TurboshaftRecreateSchedulePhase>(linkage); Run<TurboshaftRecreateSchedulePhase>(linkage);
if (data->info()->trace_turbo_graph() || FLAG_trace_turbo_scheduler) { TraceSchedule(data->info(), data, data->schedule(),
UnparkedScopeIfNeeded scope(data->broker()); TurboshaftRecreateSchedulePhase::phase_name());
AllowHandleDereference allow_deref;
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
tracing_scope.stream()
<< "\n-- Recreated Schedule ----------------------------\n"
<< *data->schedule();
}
} }
return SelectInstructions(linkage); return SelectInstructions(linkage);
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/turboshaft/graph-visualizer.h"
namespace v8::internal::compiler::turboshaft {
JSONTurboshaftGraphWriter::JSONTurboshaftGraphWriter(std::ostream& os,
const Graph& turboshaft_graph,
Zone* zone)
: os_(os),
zone_(zone),
turboshaft_graph_(turboshaft_graph) {}
void JSONTurboshaftGraphWriter::Print() {
os_ << "{\n\"nodes\":[";
PrintNodes();
os_ << "\n],\n\"edges\":[";
PrintEdges();
os_ << "\n],\n\"blocks\":[";
PrintBlocks();
os_ << "\n]}";
}
void JSONTurboshaftGraphWriter::PrintNodes() {
bool first = true;
for (const Block& block : turboshaft_graph_.blocks()) {
for (const Operation& op : turboshaft_graph_.operations(block)) {
if (!first) os_ << ",\n";
first = false;
os_ << "{\"id\":" << turboshaft_graph_.Index(op).id() << ",";
os_ << "\"title\":\"" << OpcodeName(op.opcode) << "\",";
os_ << "\"block_id\":\"" << block.index() << "\",";
os_ << "\"properties\":\"";
op.PrintOptions(os_);
os_ << "\"}";
}
}
}
void JSONTurboshaftGraphWriter::PrintEdges() {
bool first = true;
for (const Block& block : turboshaft_graph_.blocks()) {
for (const Operation& op : turboshaft_graph_.operations(block)) {
int target_id = turboshaft_graph_.Index(op).id();
for (OpIndex input : op.inputs()) {
if (!first) os_ << ",\n";
first = false;
os_ << "{\"source\":" << input.id() << ",";
os_ << "\"target\":" << target_id << "}";
}
}
}
}
void JSONTurboshaftGraphWriter::PrintBlocks() {
bool first_block = true;
for (const Block& block : turboshaft_graph_.blocks()) {
if (!first_block) os_ << ",\n";
first_block = false;
os_ << "{\"id\":\"" << block.index() << "\",";
os_ << "\"type\":\"" << block.kind() << "\",";
os_ << "\"deferred\":" << std::boolalpha << block.IsDeferred() << ",";
os_ << "\"predecessors\":[";
bool first_predecessor = true;
for (const Block* pred : block.Predecessors()) {
if (!first_predecessor) os_ << ", ";
first_predecessor = false;
os_ << "\"" << pred->index() << "\"";
}
os_ << "]}";
}
}
std::ostream& operator<<(std::ostream& os, const TurboshaftGraphAsJSON& ad) {
JSONTurboshaftGraphWriter writer(os, ad.turboshaft_graph, ad.temp_zone);
writer.Print();
return os;
}
} // namespace v8::internal::compiler::turboshaft
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_TURBOSHAFT_GRAPH_VISUALIZER_H_
#define V8_COMPILER_TURBOSHAFT_GRAPH_VISUALIZER_H_
#include "src/compiler/turboshaft/graph.h"
#include "src/common/globals.h"
#include "src/handles/handles.h"
namespace v8::internal::compiler::turboshaft {
struct TurboshaftGraphAsJSON {
TurboshaftGraphAsJSON(const Graph& tg, Zone* z): turboshaft_graph(tg),
temp_zone(z){}
const Graph& turboshaft_graph;
Zone* temp_zone;
};
V8_INLINE V8_EXPORT_PRIVATE TurboshaftGraphAsJSON AsJSON(const Graph& tg,
Zone* z) {
return TurboshaftGraphAsJSON(tg, z);
}
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const TurboshaftGraphAsJSON& ad);
class JSONTurboshaftGraphWriter {
public:
JSONTurboshaftGraphWriter(std::ostream& os, const Graph& turboshaft_graph,
Zone* zone);
JSONTurboshaftGraphWriter(const JSONTurboshaftGraphWriter&) = delete;
JSONTurboshaftGraphWriter& operator=(const JSONTurboshaftGraphWriter&) = delete;
void Print();
protected:
void PrintNodes();
void PrintEdges();
void PrintBlocks();
protected:
std::ostream& os_;
Zone* zone_;
const Graph& turboshaft_graph_;
};
} // namespace v8::internal::compiler::turboshaft
#endif // V8_COMPILER_TURBOSHAFT_GRAPH_VISUALIZER_H_
...@@ -10,9 +10,7 @@ namespace v8::internal::compiler::turboshaft { ...@@ -10,9 +10,7 @@ namespace v8::internal::compiler::turboshaft {
std::ostream& operator<<(std::ostream& os, PrintAsBlockHeader block_header) { std::ostream& operator<<(std::ostream& os, PrintAsBlockHeader block_header) {
const Block& block = block_header.block; const Block& block = block_header.block;
const char* block_type = os << "\n" << block.kind() << " " << block.index();
block.IsLoop() ? "LOOP" : block.IsMerge() ? "MERGE" : "BLOCK";
os << "\n" << block_type << " " << block.index();
if (block.IsDeferred()) os << " (deferred)"; if (block.IsDeferred()) os << " (deferred)";
if (!block.Predecessors().empty()) { if (!block.Predecessors().empty()) {
os << " <- "; os << " <- ";
...@@ -36,4 +34,19 @@ std::ostream& operator<<(std::ostream& os, const Graph& graph) { ...@@ -36,4 +34,19 @@ std::ostream& operator<<(std::ostream& os, const Graph& graph) {
return os; return os;
} }
std::ostream& operator<<(std::ostream& os, const Block::Kind& kind) {
switch (kind) {
case Block::Kind::kLoopHeader:
os << "LOOP";
break;
case Block::Kind::kMerge:
os << "MERGE";
break;
case Block::Kind::kBranchTarget:
os << "BLOCK";
break;
}
return os;
}
} // namespace v8::internal::compiler::turboshaft } // namespace v8::internal::compiler::turboshaft
...@@ -518,6 +518,7 @@ struct PrintAsBlockHeader { ...@@ -518,6 +518,7 @@ struct PrintAsBlockHeader {
}; };
std::ostream& operator<<(std::ostream& os, PrintAsBlockHeader block); std::ostream& operator<<(std::ostream& os, PrintAsBlockHeader block);
std::ostream& operator<<(std::ostream& os, const Graph& graph); std::ostream& operator<<(std::ostream& os, const Graph& graph);
std::ostream& operator<<(std::ostream& os, const Block::Kind& kind);
} // namespace v8::internal::compiler::turboshaft } // namespace v8::internal::compiler::turboshaft
......
...@@ -34,14 +34,7 @@ std::ostream& operator<<(std::ostream& os, OperationPrintStyle styled_op) { ...@@ -34,14 +34,7 @@ std::ostream& operator<<(std::ostream& os, OperationPrintStyle styled_op) {
os << styled_op.op_index_prefix << input.id(); os << styled_op.op_index_prefix << input.id();
} }
os << ")"; os << ")";
switch (op.opcode) { op.PrintOptions(os);
#define SWITCH_CASE(Name) \
case Opcode::k##Name: \
op.Cast<Name##Op>().PrintOptions(os); \
break;
TURBOSHAFT_OPERATION_LIST(SWITCH_CASE)
#undef SWITCH_CASE
}
return os; return os;
} }
...@@ -122,6 +115,17 @@ std::ostream& operator<<(std::ostream& os, ProjectionOp::Kind kind) { ...@@ -122,6 +115,17 @@ std::ostream& operator<<(std::ostream& os, ProjectionOp::Kind kind) {
} }
} }
void Operation::PrintOptions(std::ostream& os) const {
switch (opcode) {
#define SWITCH_CASE(Name) \
case Opcode::k##Name: \
Cast<Name##Op>().PrintOptions(os); \
break;
TURBOSHAFT_OPERATION_LIST(SWITCH_CASE)
#undef SWITCH_CASE
}
}
void PendingLoopPhiOp::PrintOptions(std::ostream& os) const { void PendingLoopPhiOp::PrintOptions(std::ostream& os) const {
os << "[" << rep << ", #o" << old_backedge_index.id() << "]"; os << "[" << rep << ", #o" << old_backedge_index.id() << "]";
} }
......
...@@ -267,6 +267,7 @@ struct alignas(OpIndex) Operation { ...@@ -267,6 +267,7 @@ struct alignas(OpIndex) Operation {
const OpProperties& properties() const; const OpProperties& properties() const;
std::string ToString() const; std::string ToString() const;
void PrintOptions(std::ostream& os) const;
protected: protected:
// Operation objects store their inputs behind the object. Therefore, they can // Operation objects store their inputs behind the object. Therefore, they can
......
...@@ -359,6 +359,7 @@ class RuntimeCallTimer final { ...@@ -359,6 +359,7 @@ class RuntimeCallTimer final {
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, OptimizeMoves) \ ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, OptimizeMoves) \
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PopulatePointerMaps) \ ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PopulatePointerMaps) \
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PrintGraph) \ ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PrintGraph) \
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PrintTurboshaftGraph) \
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ResolveControlFlow) \ ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ResolveControlFlow) \
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ResolvePhis) \ ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ResolvePhis) \
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \ ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \
......
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