#ifndef V8_MAGLEV_MAGLEV_GRAPH_OPTIMIZER_H_
#define V8_MAGLEV_MAGLEV_GRAPH_OPTIMIZER_H_
#include <initializer_list>
#include "src/base/logging.h"
#include "src/codegen/bailout-reason.h"
#include "src/common/scoped-modification.h"
#include "src/deoptimizer/deoptimize-reason.h"
#include "src/maglev/maglev-basic-block.h"
#include "src/maglev/maglev-graph-processor.h"
#include "src/maglev/maglev-graph.h"
#include "src/maglev/maglev-ir.h"
#include "src/maglev/maglev-kna-processor.h"
#include "src/maglev/maglev-range-analysis.h"
#include "src/maglev/maglev-reducer.h"
namespace v8 {
namespace internal {
namespace maglev {
class MaglevGraphOptimizer {
public:
explicit MaglevGraphOptimizer(
Graph* graph, RecomputeKnownNodeAspectsProcessor& kna_processor,
NodeRanges* ranges = nullptr);
void PreProcessGraph(Graph* graph) {}
void PostProcessGraph(Graph* graph) {}
BlockProcessResult PreProcessBasicBlock(BasicBlock* block);
void PostProcessBasicBlock(BasicBlock* block);
void PostPhiProcessing() {}
#define DECLARE_PROCESS(NodeT) \
ProcessResult Visit##NodeT(NodeT*, const ProcessingState&); \
ProcessResult Process(NodeT* node, const ProcessingState& state) { \
ScopedModification<NodeBase*> current_node(¤t_node_, node); \
UnwrapInputs(); \
PreProcessNode(node, state); \
ProcessResult result = Visit##NodeT(node, state); \
PostProcessNode(node); \
return result; \
}
NODE_BASE_LIST(DECLARE_PROCESS)
#undef DECLARE_PROCESS
KnownNodeAspects& known_node_aspects() {
return kna_processor_.known_node_aspects();
}
DeoptFrame* GetDeoptFrameForEagerDeopt() {
DCHECK(current_node()->properties().can_eager_deopt() ||
current_node()->properties().is_deopt_checkpoint());
return ¤t_node()->eager_deopt_info()->top_frame();
}
std::tuple<DeoptFrame*, interpreter::Register, int> GetDeoptFrameForLazyDeopt(
bool can_throw) {
DCHECK(current_node()->properties().can_lazy_deopt());
LazyDeoptInfo* info = current_node()->lazy_deopt_info();
return std::make_tuple(&info->top_frame(), info->result_location(),
info->result_size());
}
void AttachExceptionHandlerInfo(Node* node) {
DCHECK(node->properties().can_throw());
DCHECK(current_node()->properties().can_throw());
DCHECK(!node->Is<CallKnownJSFunction>());
ExceptionHandlerInfo* info = current_node()->exception_handler_info();
if (info->ShouldLazyDeopt()) {
new (node->exception_handler_info())
ExceptionHandlerInfo(ExceptionHandlerInfo::kLazyDeopt);
} else if (!info->HasExceptionHandler()) {
new (node->exception_handler_info()) ExceptionHandlerInfo();
} else {
new (node->exception_handler_info())
ExceptionHandlerInfo(info->catch_block(), info->depth());
}
}
ReduceResult EmitUnconditionalDeopt(DeoptimizeReason);
private:
MaglevReducer<MaglevGraphOptimizer> reducer_;
RecomputeKnownNodeAspectsProcessor& kna_processor_;
NodeRanges* ranges_;
NodeBase* current_node_;
NodeBase* current_node() const {
CHECK_NOT_NULL(current_node_);
return current_node_;
}
compiler::JSHeapBroker* broker() const;
std::optional<Range> GetRange(ValueNode* node);
bool IsRangeLessEqual(ValueNode* lhs, ValueNode* rhs);
void UnwrapDeoptFrames();
void UnwrapInputs();
template <typename NodeT>
ValueNode* TrySmiTag(Input input);
ValueNode* GetConstantWithRepresentation(
ValueNode* node, UseRepresentation repr,
std::optional<TaggedToFloat64ConversionType> conversion_type);
MaybeReduceResult GetUntaggedValueWithRepresentation(
ValueNode* node, UseRepresentation repr,
std::optional<TaggedToFloat64ConversionType> conversion_type);
void PreProcessNode(Node*, const ProcessingState& state);
void PostProcessNode(Node*);
void PreProcessNode(Phi*, const ProcessingState& state);
void PostProcessNode(Phi*);
void PreProcessNode(ControlNode*, const ProcessingState& state);
void PostProcessNode(ControlNode*);
Jump* FoldBranch(BasicBlock* current, BranchControlNode* branch_node,
bool if_true);
ProcessResult ReplaceWith(ValueNode* node);
template <typename NodeT, typename... Args>
ProcessResult ReplaceWith(std::initializer_list<ValueNode*> inputs,
Args&&...);
template <Operation kOperation>
std::optional<ProcessResult> TryFoldInt32Operation(ValueNode* node);
template <Operation kOperation>
std::optional<ProcessResult> TryFoldFloat64Operation(ValueNode* node);
template <typename NodeT>
ProcessResult ProcessLoadContextSlot(NodeT* node);
template <typename NodeT>
ProcessResult ProcessCheckMaps(NodeT* node, ValueNode* object_map = nullptr);
ProcessResult EmitAbort(AbortReason);
};
}
}
}
#endif