[turboshaft] Generating JSON from Turboshaft graphs
Change-Id: If1414fd2c01816461983d9bcebeaef5785ef355a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3669694 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#80809}
This commit is contained in:
parent
2117278882
commit
010e15a7e3
@ -2827,6 +2827,8 @@ filegroup(
|
||||
"src/compiler/turboshaft/graph-builder.h",
|
||||
"src/compiler/turboshaft/graph.cc",
|
||||
"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.h",
|
||||
"src/compiler/turboshaft/optimization-phase.cc",
|
||||
|
2
BUILD.gn
2
BUILD.gn
@ -2909,6 +2909,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/compiler/turboshaft/assembler.h",
|
||||
"src/compiler/turboshaft/deopt-data.h",
|
||||
"src/compiler/turboshaft/graph-builder.h",
|
||||
"src/compiler/turboshaft/graph-visualizer.h",
|
||||
"src/compiler/turboshaft/graph.h",
|
||||
"src/compiler/turboshaft/operations.h",
|
||||
"src/compiler/turboshaft/optimization-phase.h",
|
||||
@ -4117,6 +4118,7 @@ v8_source_set("v8_turboshaft") {
|
||||
|
||||
sources = [
|
||||
"src/compiler/turboshaft/graph-builder.cc",
|
||||
"src/compiler/turboshaft/graph-visualizer.cc",
|
||||
"src/compiler/turboshaft/graph.cc",
|
||||
"src/compiler/turboshaft/operations.cc",
|
||||
"src/compiler/turboshaft/optimization-phase.cc",
|
||||
|
@ -77,6 +77,7 @@
|
||||
#include "src/compiler/store-store-elimination.h"
|
||||
#include "src/compiler/turboshaft/assembler.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/optimization-phase.h"
|
||||
#include "src/compiler/turboshaft/recreate-schedule.h"
|
||||
@ -965,15 +966,12 @@ void PrintCode(Isolate* isolate, Handle<Code> code,
|
||||
#endif // ENABLE_DISASSEMBLER
|
||||
}
|
||||
|
||||
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");
|
||||
void TraceSchedule(OptimizedCompilationInfo* info, PipelineData* data,
|
||||
Schedule* schedule, const char* phase_name) {
|
||||
if (info->trace_turbo_json()) {
|
||||
UnparkedScopeIfNeeded scope(data->broker());
|
||||
AllowHandleDereference allow_deref;
|
||||
|
||||
TurboJsonFile json_of(info, std::ios_base::app);
|
||||
json_of << "{\"name\":\"" << phase_name << "\",\"type\":\"schedule\""
|
||||
<< ",\"data\":\"";
|
||||
@ -985,14 +983,26 @@ void TraceScheduleAndVerify(OptimizedCompilationInfo* info, PipelineData* data,
|
||||
}
|
||||
json_of << "\"},\n";
|
||||
}
|
||||
|
||||
if (info->trace_turbo_graph() || FLAG_trace_turbo_scheduler) {
|
||||
UnparkedScopeIfNeeded scope(data->broker());
|
||||
AllowHandleDereference allow_deref;
|
||||
|
||||
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
|
||||
tracing_scope.stream()
|
||||
<< "-- Schedule --------------------------------------\n"
|
||||
<< "----- " << phase_name << " -----\n"
|
||||
<< *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);
|
||||
}
|
||||
@ -2493,7 +2503,6 @@ struct FinalizeCodePhase {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct PrintGraphPhase {
|
||||
DECL_PIPELINE_PHASE_CONSTANTS(PrintGraph)
|
||||
|
||||
@ -2524,19 +2533,44 @@ struct PrintGraphPhase {
|
||||
AllowHandleDereference allow_deref;
|
||||
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
|
||||
tracing_scope.stream()
|
||||
<< "-- Graph after " << phase << " -- " << std::endl
|
||||
<< "----- Graph after " << phase << " ----- " << std::endl
|
||||
<< AsScheduledGraph(schedule);
|
||||
} else if (info->trace_turbo_graph()) { // Simple textual RPO.
|
||||
UnparkedScopeIfNeeded scope(data->broker());
|
||||
AllowHandleDereference allow_deref;
|
||||
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
|
||||
tracing_scope.stream()
|
||||
<< "-- Graph after " << phase << " -- " << std::endl
|
||||
<< "----- Graph after " << phase << " ----- " << std::endl
|
||||
<< 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 {
|
||||
DECL_PIPELINE_PHASE_CONSTANTS(VerifyGraph)
|
||||
@ -2883,26 +2917,14 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
|
||||
|
||||
if (FLAG_turboshaft) {
|
||||
Run<BuildTurboshaftPhase>();
|
||||
if (data->info()->trace_turbo_graph()) {
|
||||
UnparkedScopeIfNeeded scope(data->broker());
|
||||
AllowHandleDereference allow_deref;
|
||||
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
|
||||
tracing_scope.stream()
|
||||
<< "\n-- Turboshaft Graph ----------------------------\n"
|
||||
<< data->turboshaft_graph();
|
||||
}
|
||||
Run<PrintTurboshaftGraphPhase>(BuildTurboshaftPhase::phase_name());
|
||||
|
||||
Run<OptimizeTurboshaftPhase>();
|
||||
Run<PrintTurboshaftGraphPhase>(OptimizeTurboshaftPhase::phase_name());
|
||||
|
||||
Run<TurboshaftRecreateSchedulePhase>(linkage);
|
||||
if (data->info()->trace_turbo_graph() || FLAG_trace_turbo_scheduler) {
|
||||
UnparkedScopeIfNeeded scope(data->broker());
|
||||
AllowHandleDereference allow_deref;
|
||||
CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
|
||||
tracing_scope.stream()
|
||||
<< "\n-- Recreated Schedule ----------------------------\n"
|
||||
<< *data->schedule();
|
||||
}
|
||||
TraceSchedule(data->info(), data, data->schedule(),
|
||||
TurboshaftRecreateSchedulePhase::phase_name());
|
||||
}
|
||||
|
||||
return SelectInstructions(linkage);
|
||||
|
82
src/compiler/turboshaft/graph-visualizer.cc
Normal file
82
src/compiler/turboshaft/graph-visualizer.cc
Normal file
@ -0,0 +1,82 @@
|
||||
// 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
|
53
src/compiler/turboshaft/graph-visualizer.h
Normal file
53
src/compiler/turboshaft/graph-visualizer.h
Normal file
@ -0,0 +1,53 @@
|
||||
// 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 {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, PrintAsBlockHeader block_header) {
|
||||
const Block& block = block_header.block;
|
||||
const char* block_type =
|
||||
block.IsLoop() ? "LOOP" : block.IsMerge() ? "MERGE" : "BLOCK";
|
||||
os << "\n" << block_type << " " << block.index();
|
||||
os << "\n" << block.kind() << " " << block.index();
|
||||
if (block.IsDeferred()) os << " (deferred)";
|
||||
if (!block.Predecessors().empty()) {
|
||||
os << " <- ";
|
||||
@ -36,4 +34,19 @@ std::ostream& operator<<(std::ostream& os, const Graph& graph) {
|
||||
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
|
||||
|
@ -518,6 +518,7 @@ struct PrintAsBlockHeader {
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, PrintAsBlockHeader block);
|
||||
std::ostream& operator<<(std::ostream& os, const Graph& graph);
|
||||
std::ostream& operator<<(std::ostream& os, const Block::Kind& kind);
|
||||
|
||||
} // namespace v8::internal::compiler::turboshaft
|
||||
|
||||
|
@ -34,14 +34,7 @@ std::ostream& operator<<(std::ostream& os, OperationPrintStyle styled_op) {
|
||||
os << styled_op.op_index_prefix << input.id();
|
||||
}
|
||||
os << ")";
|
||||
switch (op.opcode) {
|
||||
#define SWITCH_CASE(Name) \
|
||||
case Opcode::k##Name: \
|
||||
op.Cast<Name##Op>().PrintOptions(os); \
|
||||
break;
|
||||
TURBOSHAFT_OPERATION_LIST(SWITCH_CASE)
|
||||
#undef SWITCH_CASE
|
||||
}
|
||||
op.PrintOptions(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
os << "[" << rep << ", #o" << old_backedge_index.id() << "]";
|
||||
}
|
||||
|
@ -267,6 +267,7 @@ struct alignas(OpIndex) Operation {
|
||||
const OpProperties& properties() const;
|
||||
|
||||
std::string ToString() const;
|
||||
void PrintOptions(std::ostream& os) const;
|
||||
|
||||
protected:
|
||||
// Operation objects store their inputs behind the object. Therefore, they can
|
||||
|
@ -359,6 +359,7 @@ class RuntimeCallTimer final {
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, OptimizeMoves) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PopulatePointerMaps) \
|
||||
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, ResolvePhis) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \
|
||||
|
Loading…
Reference in New Issue
Block a user