5#ifndef V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_H_
6#define V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_H_
25#if V8_ENABLE_WEBASSEMBLY
39class InstructionSelectorT;
41class OperandGeneratorT;
44class TurbofanStateObjectDeduplicator;
45class TurboshaftStateObjectDeduplicator;
53 kEnableRootsRelativeAddressing
57 kEnableSwitchJumpTable
64 explicit Features(
unsigned bits) : bits_(bits) {}
79 size_t* max_pushed_argument_count,
81 Features features = SupportedFeatures(),
86 kDisableRootsRelativeAddressing,
91 std::optional<BailoutReason> SelectInstructions();
97 return Features(CpuFeatures::SupportedFeatures());
101 const std::map<NodeId, int> GetVirtualRegistersForTesting()
const;
450 size_t* max_unoptimized_frame_height,
size_t* max_pushed_argument_count,
455 v8_flags.turbo_instruction_scheduling
459 enable_roots_relative_addressing =
641 size_t projection_index);
642 template <
typename Op>
645 return InputsImpl(op, std::make_index_sequence<Op::input_count>());
647 template <
typename Op, std::size_t...
Is>
649 return std::make_tuple(op.input(
Is)...);
771 int return_count,
int stack_slot_delta = 0);
816#define DECLARE_GENERATOR_T(x) void Visit##x(turboshaft::OpIndex node);
1040#undef DECLARE_GENERATOR_T
1112#if V8_ENABLE_WEBASSEMBLY
1115 template <const
int simd_size = kSimd128Size>
1116 void CanonicalizeShuffle(TurboshaftAdapter::SimdShuffleView& view,
1117 uint8_t* shuffle,
bool* is_swizzle)
1122 DCHECK(view.isSimd128());
1125 DCHECK(!view.isSimd128());
1134 &needs_swap, is_swizzle);
1136 SwapShuffleInputs(view);
1141 view.DuplicateFirstInput();
1147 void SwapShuffleInputs(TurboshaftAdapter::SimdShuffleView& node);
1149#if V8_ENABLE_WASM_DEINTERLEAVED_MEM_OPS
1153#if V8_ENABLE_WASM_SIMD256_REVEC
1156#ifdef V8_TARGET_ARCH_X64
1164#ifdef V8_TARGET_ARCH_X64
1206#if V8_TARGET_ARCH_64_BIT
1212 enum class Upper32BitsState : uint8_t {
1229 static_cast<size_t>(source.kind));
1241 struct CachedStateValues;
1242 class CachedStateValuesBuilder;
1293#if V8_TARGET_ARCH_64_BIT
static constexpr U encode(T value)
static unsigned SupportedFeatures()
static LinkageLocation ForAnyRegister(MachineType type=MachineType::None())
FlagsCondition condition() const
uint32_t num_conditional_compares_
turboshaft::OpIndex frame_state_or_result_
static FlagsContinuationT ForDeoptimize(FlagsCondition condition, DeoptimizeReason reason, uint32_t node_id, FeedbackSource const &feedback, turboshaft::OpIndex frame_state)
static FlagsContinuationT ForConditionalSet(compare_chain_t &compares, uint32_t num_conditional_compares, FlagsCondition set_condition, turboshaft::OpIndex result)
turboshaft::OpIndex result() const
turboshaft::OpIndex false_value() const
FlagsContinuationT(FlagsCondition condition, TrapId trap_id)
DeoptimizeReason reason() const
FeedbackSource const & feedback() const
const compare_chain_t & compares() const
static FlagsContinuationT ForConditionalBranch(compare_chain_t &compares, uint32_t num_conditional_compares, FlagsCondition branch_condition, turboshaft::Block *true_block, turboshaft::Block *false_block)
static FlagsContinuationT ForSelect(FlagsCondition condition, turboshaft::OpIndex result, turboshaft::OpIndex true_value, turboshaft::OpIndex false_value)
compare_chain_t compares_
FlagsContinuationT(FlagsCondition condition, turboshaft::OpIndex result, turboshaft::OpIndex true_value, turboshaft::OpIndex false_value)
turboshaft::OpIndex true_value_
bool IsConditionalSet() const
turboshaft::Block * false_block() const
void OverwriteAndNegateIfEqual(FlagsCondition condition)
turboshaft::Block * true_block() const
FlagsCondition final_condition_
FlagsContinuationT(FlagsMode mode, FlagsCondition condition, turboshaft::Block *true_block, turboshaft::Block *false_block)
bool IsConditionalBranch() const
InstructionCode Encode(InstructionCode opcode)
void OverwriteUnsignedIfSigned()
void Overwrite(FlagsCondition condition)
turboshaft::OpIndex false_value_
static FlagsContinuationT ForSet(FlagsCondition condition, turboshaft::OpIndex result)
uint32_t num_conditional_compares() const
FlagsContinuationT(compare_chain_t &compares, uint32_t num_conditional_compares, FlagsCondition set_condition, turboshaft::OpIndex result)
turboshaft::OpIndex true_value() const
static constexpr size_t kMaxCompareChainSize
bool IsDeoptimize() const
turboshaft::OpIndex frame_state() const
turboshaft::Block * true_block_
FlagsCondition condition_
turboshaft::Block * false_block_
FlagsContinuationT(FlagsMode mode, FlagsCondition condition, DeoptimizeReason reason, uint32_t node_id, FeedbackSource const &feedback, turboshaft::OpIndex frame_state)
static FlagsContinuationT ForDeoptimizeForTesting(FlagsCondition condition, DeoptimizeReason reason, uint32_t node_id, FeedbackSource const &feedback, turboshaft::OpIndex frame_state)
FlagsContinuationT(compare_chain_t &compares, uint32_t num_conditional_compares, FlagsCondition branch_condition, turboshaft::Block *true_block, turboshaft::Block *false_block)
FlagsCondition final_condition() const
FlagsContinuationT(FlagsCondition condition, turboshaft::OpIndex result)
std::array< ConditionalCompare, kMaxCompareChainSize > compare_chain_t
static FlagsContinuationT ForBranch(FlagsCondition condition, turboshaft::Block *true_block, turboshaft::Block *false_block)
static FlagsContinuationT ForTrap(FlagsCondition condition, TrapId trap_id)
static bool SchedulerSupported()
bool CanUseRootsRegister() const
size_t * max_pushed_argument_count_
void VisitBitcastWord32PairToFloat64(turboshaft::OpIndex node)
void VisitThrow(Node *node)
bool IsUsed(turboshaft::OpIndex node) const
void SetRename(turboshaft::OpIndex node, turboshaft::OpIndex rename)
int GetVirtualRegister(turboshaft::OpIndex node)
void VisitTrapIf(turboshaft::OpIndex node)
void TryRename(InstructionOperand *op)
size_t * max_unoptimized_frame_height_
IntVector virtual_registers_
void MarkPairProjectionsAsWord32(turboshaft::OpIndex node)
void EndBlock(RpoNumber rpo)
turboshaft::Graph * schedule() const
void VisitDeadValue(Node *node)
void MarkAsSimd128(turboshaft::OpIndex node)
InstructionSequence *const sequence_
size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor *descriptor, turboshaft::OpIndex state, OperandGenerator *g, StateObjectDeduplicator *deduplicator, InstructionOperandVector *inputs, FrameStateInputKind kind, Zone *zone)
source_position_table_t *const source_positions_
const ZoneVector< std::pair< int, int > > & instr_origins() const
void VisitSelect(turboshaft::OpIndex node)
void VisitWordCompareZero(turboshaft::OpIndex user, turboshaft::OpIndex value, FlagsContinuation *cont)
void VisitBlock(const turboshaft::Block *block)
FlagsCondition GetComparisonFlagCondition(const turboshaft::ComparisonOp &op) const
void AddOutputToSelectContinuation(OperandGenerator *g, int first_input_index, turboshaft::OpIndex node)
Linkage * linkage() const
bool CanDoBranchIfOverflowFusion(turboshaft::OpIndex node)
void VisitDynamicCheckMapsWithDeoptUnless(Node *node)
void EmitPrepareArguments(ZoneVector< PushParameter > *arguments, const CallDescriptor *call_descriptor, turboshaft::OpIndex node)
void VisitFinishRegion(Node *node)
void VisitOsrValue(turboshaft::OpIndex node)
void VisitI8x16RelaxedSwizzle(turboshaft::OpIndex node)
void MarkAsSimd256(turboshaft::OpIndex node)
Instruction * Emit(InstructionCode opcode, InstructionOperand output, size_t temp_count=0, InstructionOperand *temps=nullptr)
void VisitNode(turboshaft::OpIndex node)
void MarkAsFloat64(turboshaft::OpIndex node)
Isolate * isolate() const
InstructionSelector::EnableRootsRelativeAddressing enable_roots_relative_addressing_
bool CanCover(turboshaft::OpIndex user, turboshaft::OpIndex node) const
bool IsDefined(turboshaft::OpIndex node) const
void MarkAsRepresentation(MachineRepresentation rep, turboshaft::OpIndex node)
InstructionSelector::EnableSwitchJumpTable enable_switch_jump_table_
ZoneVector< std::pair< int, int > > instr_origins_
FlagsContinuationT FlagsContinuation
void StartBlock(RpoNumber rpo)
void AddInstruction(Instruction *instr)
InstructionScheduler * scheduler_
FrameStateDescriptor * GetFrameStateDescriptor(turboshaft::OpIndex node)
InstructionSelector::Features Features
void MarkAsDefined(turboshaft::OpIndex node)
void UpdateMaxPushedArgumentCount(size_t count)
void TryPrepareScheduleFirstProjection(turboshaft::OpIndex maybe_projection)
std::optional< BitVector > additional_protected_instructions_
bool IsReallyUsed(turboshaft::OpIndex node) const
void EmitMoveFPRToParam(InstructionOperand *op, LinkageLocation location)
void VisitConstant(turboshaft::OpIndex node)
void AddTerminator(Instruction *instr)
Instruction * EmitWithContinuation(InstructionCode opcode, FlagsContinuation *cont)
turboshaft::OpIndex block_terminator(const turboshaft::Block *block) const
void MarkAsRepresentation(turboshaft::RegisterRepresentation rep, turboshaft::OpIndex node)
void VisitWord64AtomicBinaryOperation(turboshaft::OpIndex node, ArchOpcode uint8_op, ArchOpcode uint16_op, ArchOpcode uint32_op, ArchOpcode uint64_op)
void EmitIdentity(turboshaft::OpIndex node)
void UpdateRenamesInPhi(PhiInstruction *phi)
std::optional< BitVector > protected_loads_to_remove_
void VisitLoadTransform(Node *node, Node *value, InstructionCode opcode)
bool instruction_selection_failed()
bool instruction_selection_failed_
void VisitDeoptimizeIf(turboshaft::OpIndex node)
const std::map< uint32_t, int > GetVirtualRegistersForTesting() const
auto InputsImpl(const Op &op, std::index_sequence< Is... >)
size_t AddOperandToStateValueDescriptor(StateValueList *values, InstructionOperandVector *inputs, OperandGenerator *g, StateObjectDeduplicator *deduplicator, turboshaft::OpIndex input, MachineType type, FrameStateInputKind kind, Zone *zone)
bool UseInstructionScheduling() const
InstructionOperandVector continuation_outputs_
void SetProtectedLoadToRemove(turboshaft::OpIndex node)
static Features SupportedFeatures()
void InitializeCallBuffer(turboshaft::OpIndex call, CallBuffer *buffer, CallBufferFlags flags, turboshaft::OpIndex callee, turboshaft::OptionalOpIndex frame_state_opt, base::Vector< const turboshaft::OpIndex > arguments, int return_count, int stack_slot_delta=0)
bool CanCoverProtectedLoad(turboshaft::OpIndex user, turboshaft::OpIndex node) const
void VisitDeoptimize(DeoptimizeReason reason, uint32_t node_id, FeedbackSource const &feedback, turboshaft::OpIndex frame_state)
void EmitTableSwitch(const SwitchInfo &sw, InstructionOperand const &index_operand)
JSHeapBroker *const broker_
void MarkAsCompressed(turboshaft::OpIndex node)
void SetEffectLevel(turboshaft::OpIndex node, int effect_level)
void VisitControl(const turboshaft::Block *block)
void VisitUnreachable(turboshaft::OpIndex node)
bool IsSupported(CpuFeature feature) const
void MarkAsUsed(turboshaft::OpIndex node)
size_t AddInputsToFrameStateDescriptor(StateValueList *values, InstructionOperandVector *inputs, OperandGenerator *g, StateObjectDeduplicator *deduplicator, turboshaft::OpIndex node, FrameStateInputKind kind, Zone *zone)
InstructionSelector::EnableScheduling enable_scheduling_
bool IsTailCallAddressImmediate()
bool CanProduceSignalingNaN(Node *node)
void VisitTailCall(turboshaft::OpIndex call)
void MarkAsWord32(turboshaft::OpIndex node)
void VisitStackPointerGreaterThan(turboshaft::OpIndex node, FlagsContinuation *cont)
bool IsReallyLive(turboshaft::OpIndex node) const
std::optional< BailoutReason > SelectInstructions()
Zone * instruction_zone() const
void ConsumeEqualZero(turboshaft::OpIndex *user, turboshaft::OpIndex *value, FlagsContinuation *cont)
void set_instruction_selection_failed()
void UpdateRenames(Instruction *instruction)
turboshaft::OptionalOpIndex FindProjection(turboshaft::OpIndex node, size_t projection_index)
int GetRename(int virtual_register)
int current_effect_level_
@ kCallFixedTargetRegister
InstructionSelectorT(Zone *zone, size_t node_count, Linkage *linkage, InstructionSequence *sequence, turboshaft::Graph *schedule, source_position_table_t *source_positions, Frame *frame, InstructionSelector::EnableSwitchJumpTable enable_switch_jump_table, TickCounter *tick_counter, JSHeapBroker *broker, size_t *max_unoptimized_frame_height, size_t *max_pushed_argument_count, InstructionSelector::SourcePositionMode source_position_mode=InstructionSelector::kCallSourcePositions, Features features=SupportedFeatures(), InstructionSelector::EnableScheduling enable_scheduling=v8_flags.turbo_instruction_scheduling ? InstructionSelector::kEnableScheduling :InstructionSelector::kDisableScheduling, InstructionSelector::EnableRootsRelativeAddressing enable_roots_relative_addressing=InstructionSelector::kDisableRootsRelativeAddressing, InstructionSelector::EnableTraceTurboJson trace_turbo=InstructionSelector::kDisableTraceTurboJson)
void VisitLoad(turboshaft::OpIndex node, turboshaft::OpIndex value, InstructionCode opcode)
void VisitCall(turboshaft::OpIndex call, turboshaft::Block *handler={})
void MarkAsWord64(turboshaft::OpIndex node)
bool CanAddressRelativeToRootsRegister(const ExternalReference &reference) const
void VisitProjection(turboshaft::OpIndex node)
void VisitGoto(turboshaft::Block *target)
IntVector virtual_register_rename_
std::optional< turboshaft::UseMap > turboshaft_use_map_
const turboshaft::Block * current_block_
TickCounter *const tick_counter_
bool IsLive(turboshaft::OpIndex node) const
ZoneVector< Instruction * > instructions_
bool IsCommutative(turboshaft::OpIndex node) const
bool IsOnlyUserOfNodeInSameBlock(turboshaft::OpIndex user, turboshaft::OpIndex node) const
InstructionOperandVector continuation_temps_
int GetEffectLevel(turboshaft::OpIndex node) const
void MarkAsTagged(turboshaft::OpIndex node)
void VisitFloat64Ieee754Binop(turboshaft::OpIndex, InstructionCode code)
InstructionSelector::SourcePositionMode const source_position_mode_
void VisitIfException(turboshaft::OpIndex node)
InstructionOperandVector continuation_inputs_
turboshaft::Graph *const schedule_
auto Inputs(turboshaft::OpIndex node)
void MarkAsFloat32(turboshaft::OpIndex node)
ZoneUnorderedMap< FrameStateInput, CachedStateValues *, typename FrameStateInput::Hash, typename FrameStateInput::Equal > state_values_cache_
InstructionSequence * sequence() const
InstructionSelector::EnableTraceTurboJson trace_turbo_
void VisitSwitch(turboshaft::OpIndex node, const SwitchInfo &sw)
bool IsSourcePositionUsed(turboshaft::OpIndex node)
void VisitBranch(turboshaft::OpIndex input, turboshaft::Block *tbranch, turboshaft::Block *fbranch)
base::Vector< const turboshaft::OpIndex > turboshaft_uses(turboshaft::OpIndex node) const
void VisitPhi(turboshaft::OpIndex node)
void UpdateSourcePosition(Instruction *instruction, turboshaft::OpIndex node)
void AppendDeoptimizeArguments(InstructionOperandVector *args, DeoptimizeReason reason, uint32_t node_id, FeedbackSource const &feedback, turboshaft::OpIndex frame_state, DeoptimizeKind kind=DeoptimizeKind::kEager)
void VisitReturn(turboshaft::OpIndex node)
void VisitWord64AtomicNarrowBinop(Node *node, ArchOpcode uint8_op, ArchOpcode uint16_op, ArchOpcode uint32_op)
void EmitMoveParamToFPR(turboshaft::OpIndex node, int index)
void EmitBinarySearchSwitch(const SwitchInfo &sw, InstructionOperand const &value_operand)
void VisitParameter(turboshaft::OpIndex node)
void VisitFloat64Ieee754Unop(turboshaft::OpIndex, InstructionCode code)
void VisitWord32AtomicBinaryOperation(turboshaft::OpIndex node, ArchOpcode int8_op, ArchOpcode uint8_op, ArchOpcode int16_op, ArchOpcode uint16_op, ArchOpcode word32_op)
void MarkAsProtected(turboshaft::OpIndex node)
void VisitRetain(turboshaft::OpIndex node)
void VisitStaticAssert(turboshaft::OpIndex node)
void EmitPrepareResults(ZoneVector< PushParameter > *results, const CallDescriptor *call_descriptor, turboshaft::OpIndex node)
Features(CpuFeature f1, CpuFeature f2)
bool Contains(CpuFeature f) const
InstructionSelector & operator=(const InstructionSelector &)=delete
EnableRootsRelativeAddressing
@ kDisableRootsRelativeAddressing
@ kDisableSwitchJumpTable
static Features SupportedFeatures()
InstructionSelector(const InstructionSelector &)=delete
InstructionSelectorT * turboshaft_impl_
Isolate * isolate() const
OpIndex PreviousIndex(const OpIndex idx) const
MachineRepresentation machine_representation() const
constexpr bool valid() const
bool Is(V< AnyOrNone > op_idx) const
const underlying_operation_t< Op > & Cast(V< AnyOrNone > op_idx) const
static void CanonicalizeShuffle(bool inputs_equal, uint8_t *shuffle, bool *needs_swap, bool *is_swizzle)
base::Vector< const DirectHandle< Object > > args
SourcePositionTable * source_positions
#define DECLARE_GENERATOR_T(x)
V8_INLINE size_t hash_combine(size_t seed, size_t hash)
TNode< Float64T > Float64Add(TNode< Float64T > a, TNode< Float64T > b)
FlagsCondition CommuteFlagsCondition(FlagsCondition condition)
@ kSignedGreaterThanOrEqual
@ kUnsignedLessThanOrEqual
@ kUnsignedGreaterThanOrEqual
FlagsCondition NegateFlagsCondition(FlagsCondition condition)
@ kFlags_conditional_branch
constexpr int kSimd128Size
constexpr int kSimd256Size
V8_EXPORT_PRIVATE FlagValues v8_flags
i::Address Load(i::Address address)
#define MACHINE_SIMD256_OP_LIST(V)
#define MACHINE_SIMD128_OP_LIST(V)
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define V8_EXPORT_PRIVATE
FlagsCondition compare_condition
FlagsCondition default_flags
PushParameterT(turboshaft::OpIndex n={}, LinkageLocation l=LinkageLocation::ForAnyRegister())
base::Vector< const turboshaft::OpIndex > inputs(turboshaft::OpIndex node) const
turboshaft::Opcode opcode(turboshaft::OpIndex node) const
bool IsProtectedLoad(turboshaft::OpIndex node) const