5#ifndef V8_COMPILER_TURBOSHAFT_TYPE_INFERENCE_REDUCER_H_
6#define V8_COMPILER_TURBOSHAFT_TYPE_INFERENCE_REDUCER_H_
32 return operation.outputs_rep().size() > 0;
99 block_refinements(Asm().input_graph().block_count(), {},
103 "Type Refinements", Asm().input_graph(),
106 const std::vector<std::pair<turboshaft::OpIndex, turboshaft::Type>>&
107 refinements = block_refinements[
index];
108 if (refinements.empty())
return false;
110 for (
const auto& [op, type] : refinements) {
111 stream << op <<
" : " << type <<
"\\n";
119 "Types", Asm().input_graph(),
123 if (!type.IsInvalid() && !type.IsNone()) {
124 type.PrintTo(stream);
139 template <
Opcode opcode,
typename Continuation,
typename... Ts>
141 OpIndex index = Continuation{
this}.Reduce(
args...);
144 const Operation& op = Asm().output_graph().Get(index);
147 Asm().output_graph().
Get(index).outputs_rep(), Asm().
graph_zone());
153 template <
typename Op,
typename Continuation>
155 OpIndex og_index = Continuation{
this}.ReduceInputGraph(ig_index, operation);
156 if (!og_index.
valid())
return og_index;
177 Next::Bind(new_block);
195 std::optional<table_t::Snapshot> pred_snapshot =
197 DCHECK(pred_snapshot.has_value());
209 Type result_type = predecessors[0];
210 for (
size_t i = 1;
i < predecessors.
size(); ++
i) {
229 DCHECK(branch->if_true == new_block || branch->if_false == new_block);
231 branch->if_true == new_block);
240 const std::string branch_str = branch->
ToString().substr(0, 40);
243 Asm().output_graph().Index(*branch).id(),
250 then_branch ?
'T' :
'F');
259 char case_for_tracing) {
261 DCHECK(!type.IsInvalid());
264 " %c: %3d:%-40s ~~> %s\n", case_for_tracing, op.
id(),
265 Asm().output_graph().
Get(op).
ToString().substr(0, 40).c_str(),
266 type.ToString().c_str());
271 if (key_opt.has_value()) {
275 std::vector<std::pair<OpIndex, Type>>& refinement =
276 Asm().output_graph().block_type_refinement()[new_block->
index()];
277 refinement.push_back(std::make_pair(op, type));
286 OpIndex index = Next::ReducePendingLoopPhi(first, rep);
299 OpIndex index = Next::ReducePhi(inputs, rep);
303 for (
const OpIndex input : inputs) {
322 OpIndex index = Next::ReduceComparison(left, right,
kind, rep);
333 V<Any> index = Next::ReduceProjection(input, idx, rep);
343 V<Word> index = Next::ReduceWordBinop(left, right,
kind, rep);
355 OpIndex index = Next::ReduceOverflowCheckedBinop(left, right,
kind, rep);
367 V<Float> index = Next::ReduceFloatBinop(left, right,
kind, rep);
381 OpIndex index = Next::ReduceCheckTurboshaftTypeOf(input, rep, type,
true);
383 "CTOF %3d:%-40s\n P: %3d:%-40s ~~> %s\n", index.id(),
384 Asm().output_graph().
Get(index).
ToString().substr(0, 40).c_str(),
386 Asm().output_graph().
Get(input).
ToString().substr(0, 40).c_str(),
392 "Checking type %s of operation %d:%s failed after it passed in a "
394 type.ToString().c_str(), input.id(),
395 Asm().output_graph().
Get(input).
ToString().c_str());
398 Next::ReduceCheckTurboshaftTypeOf(input, rep, type, successful);
400 "CTOF %3d:%-40s\n F: %3d:%-40s ~~> %s\n", index.id(),
401 Asm().output_graph().
Get(index).
ToString().substr(0, 40).c_str(),
403 Asm().output_graph().
Get(input).
ToString().substr(0, 40).c_str(),
412 "REM %3d:%-40s %-40s\n", index_of_last_operation.
id(),
415 .
Get(index_of_last_operation)
422 Next::RemoveLast(index_of_last_operation);
427 const Type& ig_type) {
435 "Refi %3d:%-40s\n I: %-40s ~~> %-40s\n", index.id(),
436 Asm().output_graph().
Get(index).
ToString().substr(0, 40).c_str(),
458 if (type.IsInvalid()) {
459 const Operation& op = Asm().output_graph().Get(index);
471 bool is_fallback_for_unsupported_operation =
false) {
486 if (!is_fallback_for_unsupported_operation) {
488 "Type %3d:%-40s ==> %s\n", index.id(),
489 Asm().output_graph().
Get(index).
ToString().substr(0, 40).c_str(),
495 "TODO %3d:%-40s ==> %s\n", index.id(),
496 Asm().output_graph().
Get(index).
ToString().substr(0, 40).c_str(),
512 const auto& input_type = Asm().input_graph().operation_types()[input_index];
513 const auto& output_type = types_[output_index];
515 if (input_type.IsInvalid())
return;
516 DCHECK(!output_type.IsInvalid());
518 const bool is_okay = output_type.IsSubtypeOf(input_type);
521 "\033[%s %3d:%-40s %-40s\n %3d:%-40s %-40s\033[0m\n",
522 is_okay ?
"32mOK " :
"31mFAIL", input_index.
id(),
523 Asm().input_graph().
Get(input_index).
ToString().substr(0, 40).c_str(),
524 input_type.ToString().substr(0, 40).c_str(), output_index.
id(),
525 Asm().output_graph().
Get(output_index).
ToString().substr(0, 40).c_str(),
526 output_type.ToString().substr(0, 40).c_str());
530 "\033[%s %3d:%-40s %-40s\n %3d:%-40s %-40s\033[0m\n",
531 is_okay ?
"32mOK " :
"31mFAIL", input_index.
id(),
532 Asm().input_graph().
Get(input_index).
ToString().substr(0, 40).c_str(),
533 input_type.ToString().substr(0, 40).c_str(), output_index.
id(),
540 output_type.ToString().substr(0, 40).c_str());
553 &Asm().input_graph()};
555 Asm().output_graph().operation_types()};
559 Asm().phase_zone(), &Asm().output_graph()};
562 std::nullopt, Asm().phase_zone()};
#define REDUCE(operation)
void push_back(const T &value)
const Operation & LastOperation(const Graph &graph) const
NeighboringPredecessorIterable PredecessorsIterable() const
int PredecessorCount() const
Block * LastPredecessor() const
constexpr uint32_t id() const
constexpr bool valid() const
Key NewKey(KeyData data, Value initial_value=Value{})
const Value & Get(Key key) const
SnapshotTableKey< Type, NoKeyData > Key
void StartNewSnapshot(base::Vector< const Snapshot > predecessors, const ChangeCallback &change_callback={})
bool Set(Key key, Value new_value)
static TupleType Tuple(const Type &element0, const Type &element1, Zone *zone)
GrowingOpIndexSidetable< Type > Run(GrowingBlockSidetable< std::vector< std::pair< OpIndex, Type > > > *block_refinements=nullptr)
void RefineTypeFromInputGraph(OpIndex index, const Type &og_type, const Type &ig_type)
ZoneVector< table_t::Snapshot > predecessors_
void RefineTypesAfterBranch(const BranchOp *branch, Block *new_block, bool then_branch)
OpIndex REDUCE Phi(base::Vector< const OpIndex > inputs, RegisterRepresentation rep)
void RefineOperationType(Block *new_block, OpIndex op, const Type &type, char case_for_tracing)
TypeInferenceReducerArgs args_
V< Word32 > REDUCE Comparison(V< Any > left, V< Any > right, ComparisonOp::Kind kind, RegisterRepresentation rep)
Type GetOutputGraphType(OpIndex og_index)
OpIndex ReduceInputGraphOperation(OpIndex ig_index, const Op &operation)
TypeInferenceAnalysis analyzer_
OpIndex ReduceOperation(Ts... args)
OpIndex REDUCE CheckTurboshaftTypeOf(OpIndex input, RegisterRepresentation rep, Type type, bool successful)
void RemoveLast(OpIndex index_of_last_operation)
Type GetType(OpIndex index)
V< Float > REDUCE FloatBinop(V< Float > left, V< Float > right, FloatBinopOp::Kind kind, FloatRepresentation rep)
Type GetTypeOrInvalid(OpIndex index)
Type GetTupleType(const TupleOp &tuple)
GrowingBlockSidetable< std::optional< table_t::Snapshot > > block_to_snapshot_mapping_
bool NeedsTyping(OpIndex index) const
GrowingOpIndexSidetable< Type > & output_graph_types_
void Bind(Block *new_block)
const Block * current_block_
Type GetInputGraphType(OpIndex ig_index)
V< Word > REDUCE WordBinop(V< Word > left, V< Word > right, WordBinopOp::Kind kind, WordRepresentation rep)
void SetType(OpIndex index, const Type &result_type, bool is_fallback_for_unsupported_operation=false)
V< Any > REDUCE Projection(V< Any > input, uint16_t idx, RegisterRepresentation rep)
GrowingOpIndexSidetable< std::optional< table_t::Key > > op_to_key_mapping_
OpIndex REDUCE PendingLoopPhi(OpIndex first, RegisterRepresentation rep)
OpIndex REDUCE OverflowCheckedBinop(V< Word > left, V< Word > right, OverflowCheckedBinopOp::Kind kind, WordRepresentation rep)
GrowingOpIndexSidetable< Type > input_graph_types_
bool IsSubtypeOf(const Type &other) const
std::string ToString() const
static Type LeastUpperBound(const Type &lhs, const Type &rhs, Zone *zone)
static Type TypeConstant(ConstantOp::Kind kind, ConstantOp::Storage value)
static Type TypeWordBinop(Type left_type, Type right_type, WordBinopOp::Kind kind, WordRepresentation rep, Zone *zone)
static Type TypeOverflowCheckedBinop(const Type &left_type, const Type &right_type, OverflowCheckedBinopOp::Kind kind, WordRepresentation rep, Zone *zone)
static Type TypeProjection(const Type &input, uint16_t idx)
static Type TypeComparison(const Type &lhs, const Type &rhs, RegisterRepresentation rep, ComparisonOp::Kind kind, Zone *zone)
static Type TypeForRepresentation(RegisterRepresentation rep)
static Type TypeFloatBinop(Type left_type, Type right_type, FloatBinopOp::Kind kind, FloatRepresentation rep, Zone *zone)
#define TURBOSHAFT_REDUCER_BOILERPLATE(Name)
#define TURBOSHAFT_TRACE_TYPING_OK(str,...)
#define TURBOSHAFT_TRACE_TYPING(...)
#define TURBOSHAFT_TRACE_TYPING_FAIL(str,...)
base::Vector< const DirectHandle< Object > > args
constexpr Vector< T > VectorOf(T *start, size_t size)
V8_INLINE bool CanBeTyped(const Op &operation)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
std::string ToString(const BytecodeLivenessState &liveness)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK(condition)
#define DCHECK_GT(v1, v2)
V< Word32 > condition() const
base::Vector< OpIndex > inputs()
std::string ToString() const
const underlying_operation_t< Op > * TryCast() const
underlying_operation_t< Op > & Cast()
base::Vector< const RegisterRepresentation > outputs_rep() const
InputGraphTyping input_graph_typing
OutputGraphTyping output_graph_typing
TypeInferenceReducerArgs(InputGraphTyping input_graph_typing, OutputGraphTyping output_graph_typing)
@ kPreserveFromInputGraph
#define V8_UNLIKELY(condition)