v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
instruction-selector-impl.h
Go to the documentation of this file.
1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_IMPL_H_
6#define V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_IMPL_H_
7
13
14namespace v8 {
15namespace internal {
16namespace compiler {
17
18struct CaseInfoT {
19 int32_t value; // The case value.
20 int32_t order; // The order for lowering to comparisons (less means earlier).
22 branch; // The basic blocks corresponding to the case value.
23};
24
25inline bool operator<(const CaseInfoT& l, const CaseInfoT& r) {
26 return l.order < r.order;
27}
28
29// Helper struct containing data about a table or lookup switch.
31 public:
35 : cases_(cases),
39 if (cases.size() != 0) {
40 DCHECK_LE(min_value, max_value);
41 // Note that {value_range} can be 0 if {min_value} is -2^31 and
42 // {max_value} is 2^31-1, so don't assume that it's non-zero below.
43 value_range_ = 1u + base::bit_cast<uint32_t>(max_value) -
44 base::bit_cast<uint32_t>(min_value);
45 } else {
46 value_range_ = 0;
47 }
48 }
49
50 std::vector<CaseInfo> CasesSortedByValue() const {
51 std::vector<CaseInfo> result(cases_.begin(), cases_.end());
52 std::stable_sort(result.begin(), result.end(),
53 [](CaseInfo a, CaseInfo b) { return a.value < b.value; });
54 return result;
55 }
56 const ZoneVector<CaseInfo>& CasesUnsorted() const { return cases_; }
57 int32_t min_value() const { return min_value_; }
58 int32_t max_value() const { return max_value_; }
59 size_t value_range() const { return value_range_; }
60 size_t case_count() const { return cases_.size(); }
62
63 private:
65 int32_t min_value_; // minimum value of {cases_}
66 int32_t max_value_; // maximum value of {cases_}
67 size_t value_range_; // |max_value - min_value| + 1
69};
70
71// A helper class for the instruction selector that simplifies construction of
72// Operands. This class implements a base for architecture-specific helpers.
74 public:
77
79 return InstructionOperand(); // Generates an invalid operand.
80 }
81
87
89 int input_index) {
90 return Define(node, UnallocatedOperand(GetVReg(node), input_index));
91 }
92
96
101
102 template <typename FPRegType>
108
110 selector()->MarkAsDefined(node);
111 int virtual_register = GetVReg(node);
112 sequence()->AddConstant(virtual_register, ToConstant(node));
113 return ConstantOperand(virtual_register);
114 }
115
117 LinkageLocation location) {
118 return Define(node, ToUnallocatedOperand(location, GetVReg(node)));
119 }
120
122 LinkageLocation primary_location,
123 LinkageLocation secondary_location) {
124 return Define(node,
126 primary_location, secondary_location, GetVReg(node)));
127 }
128
134
140
146
152
159
165
171
176
177 // Use register or operand for the node. If a register is chosen, it won't
178 // alias any temporary or output registers.
183
184 // Use a unique register for the node that does not alias any temporary or
185 // output registers.
190
193 RegisterUseKind unique_reg) {
194 if (V8_LIKELY(unique_reg == RegisterUseKind::kUseRegister)) {
195 return UseRegister(node);
196 } else {
198 return UseUniqueRegister(node);
199 }
200 }
201
206
207 template <typename FPRegType>
212
214 return sequence()->AddImmediate(Constant(immediate));
215 }
216
218 return sequence()->AddImmediate(Constant(immediate));
219 }
220
224
228
230 LinkageLocation location) {
231 return Use(node, ToUnallocatedOperand(location, GetVReg(node)));
232 }
233
234 // Used to force gap moves from the from_location to the to_location
235 // immediately before an instruction.
237 LinkageLocation from_location) {
238 UnallocatedOperand casted_from_operand =
239 UnallocatedOperand::cast(TempLocation(from_location));
240 selector_->Emit(kArchNop, casted_from_operand);
241 return ToUnallocatedOperand(to_location,
242 casted_from_operand.virtual_register());
243 }
244
250
252
256
260
265
266 // The kind of register generated for memory operands. kRegister is alive
267 // until the start of the operation, kUniqueRegister until the end.
272
274 RegisterMode register_mode) {
275 return register_mode == kRegister ? UseRegister(node)
276 : UseUniqueRegister(node);
277 }
278
287
296
305
310
313 sequence()->NextVirtualRegister());
314 }
315
316 template <typename FPRegType>
320 sequence()->NextVirtualRegister());
322 op.virtual_register());
323 return op;
324 }
325
327 return sequence()->AddImmediate(Constant(imm));
328 }
329
331 return ToUnallocatedOperand(location, sequence()->NextVirtualRegister());
332 }
333
337
338 protected:
341 Zone* zone() const { return selector()->instruction_zone(); }
342
343 private:
344 int GetVReg(turboshaft::OpIndex node) const {
345 return selector_->GetVirtualRegister(node);
346 }
347
349 using Kind = turboshaft::ConstantOp::Kind;
350 if (const turboshaft::ConstantOp* constant =
351 this->turboshaft_graph()
352 ->Get(node)
354 switch (constant->kind) {
355 case Kind::kWord32:
356 return Constant(static_cast<int32_t>(constant->word32()));
357 case Kind::kWord64:
358 return Constant(static_cast<int64_t>(constant->word64()));
359 case Kind::kSmi:
360 if constexpr (Is64()) {
361 return Constant(static_cast<int64_t>(constant->smi().ptr()));
362 } else {
363 return Constant(static_cast<int32_t>(constant->smi().ptr()));
364 }
365 case Kind::kHeapObject:
366 case Kind::kCompressedHeapObject:
367 case Kind::kTrustedHeapObject:
368 return Constant(constant->handle(),
369 constant->kind == Kind::kCompressedHeapObject);
370 case Kind::kExternal:
371 return Constant(constant->external_reference());
372 case Kind::kNumber:
373 return Constant(constant->number());
374 case Kind::kFloat32:
375 return Constant(constant->float32());
376 case Kind::kFloat64:
377 return Constant(constant->float64());
378 case Kind::kTaggedIndex: {
379 // Unencoded index value.
380 intptr_t value = static_cast<intptr_t>(constant->tagged_index());
382 // Generate it as 32/64-bit constant in a tagged form.
383 Address tagged_index = TaggedIndex::FromIntptr(value).ptr();
385 return Constant(static_cast<int32_t>(tagged_index));
386 } else {
387 return Constant(static_cast<int64_t>(tagged_index));
388 }
389 }
390 case Kind::kRelocatableWasmCall:
391 case Kind::kRelocatableWasmStubCall: {
392 uint64_t value = constant->integral();
393 auto mode = constant->kind == Kind::kRelocatableWasmCall
396 using constant_type = std::conditional_t<Is64(), int64_t, int32_t>;
398 base::checked_cast<constant_type>(value), mode));
399 }
400 case Kind::kRelocatableWasmCanonicalSignatureId:
402 base::checked_cast<int32_t>(constant->integral()),
404 case Kind::kRelocatableWasmIndirectCallTarget:
405 uint64_t value = constant->integral();
407 base::checked_cast<int32_t>(value),
409 }
410 }
411 UNREACHABLE();
412 }
413
415 const turboshaft::ConstantOp& constant =
416 Get(node).Cast<turboshaft::ConstantOp>();
417 switch (constant.kind) {
419 return Constant(-static_cast<int32_t>(constant.word32()));
421 return Constant(-static_cast<int64_t>(constant.word64()));
423 if (Is64()) {
424 return Constant(-static_cast<int64_t>(constant.smi().ptr()));
425 } else {
426 return Constant(-static_cast<int32_t>(constant.smi().ptr()));
427 }
428 default:
429 UNREACHABLE();
430 }
431 }
432
434 UnallocatedOperand operand) {
435 DCHECK(node.valid());
436 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
437 selector()->MarkAsDefined(node);
438 return operand;
439 }
440
442 DCHECK(node.valid());
443 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
444 selector()->MarkAsUsed(node);
445 return operand;
446 }
447
449 LinkageLocation primary_location, LinkageLocation secondary_location,
450 int virtual_register) {
451 // We only support the primary location being a register and the secondary
452 // one a slot.
453 DCHECK(primary_location.IsRegister() &&
454 secondary_location.IsCalleeFrameSlot());
455 int reg_id = primary_location.AsRegister();
456 int slot_id = secondary_location.AsCalleeFrameSlot();
457 return UnallocatedOperand(reg_id, slot_id, virtual_register);
458 }
459
461 int virtual_register) {
462 if (location.IsAnyRegister() || location.IsNullRegister()) {
463 // any machine register.
465 virtual_register);
466 }
467 if (location.IsCallerFrameSlot()) {
468 // a location on the caller frame.
470 location.AsCallerFrameSlot(), virtual_register);
471 }
472 if (location.IsCalleeFrameSlot()) {
473 // a spill location on this (callee) frame.
475 location.AsCalleeFrameSlot(), virtual_register);
476 }
477 // a fixed register.
478 if (IsFloatingPoint(location.GetType().representation())) {
480 location.AsRegister(), virtual_register);
481 }
483 location.AsRegister(), virtual_register);
484 }
485
487};
488
489} // namespace compiler
490} // namespace internal
491} // namespace v8
492
493#endif // V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_IMPL_H_
Schedule * schedule
NO_INLINE_FOR_ARM64_MSVC bool IsRegister() const
constexpr MachineRepresentation representation() const
V8_INLINE constexpr StorageType ptr() const
static Tagged< TaggedIndex > FromIntptr(intptr_t value)
static bool constexpr IsValid(intptr_t value)
Instruction * Emit(InstructionCode opcode, InstructionOperand output, size_t temp_count=0, InstructionOperand *temps=nullptr)
void AddConstant(int virtual_register, Constant constant)
ImmediateOperand AddImmediate(const Constant &constant)
void MarkAsRepresentation(MachineRepresentation rep, int virtual_register)
Constant ToNegatedConstant(turboshaft::OpIndex node)
InstructionOperand UseUniqueSlot(turboshaft::OpIndex node)
UnallocatedOperand ToUnallocatedOperand(LinkageLocation location, int virtual_register)
InstructionOperand UsePointerLocation(LinkageLocation to_location, LinkageLocation from_location)
UnallocatedOperand Use(turboshaft::OpIndex node, UnallocatedOperand operand)
InstructionOperand UseRegister(turboshaft::OpIndex node, RegisterUseKind unique_reg)
InstructionOperand UseAnyAtEnd(turboshaft::OpIndex node)
InstructionOperand DefineAsDualLocation(turboshaft::OpIndex node, LinkageLocation primary_location, LinkageLocation secondary_location)
InstructionOperand UseLocation(turboshaft::OpIndex node, LinkageLocation location)
InstructionOperand UseFixed(turboshaft::OpIndex node, Register reg)
InstructionOperand DefineAsRegister(turboshaft::OpIndex node)
InstructionOperand UseFixed(turboshaft::OpIndex node, FPRegType reg)
InstructionOperand Use(turboshaft::OpIndex node)
Constant ToConstant(turboshaft::OpIndex node)
InstructionOperand UseNegatedImmediate(turboshaft::OpIndex node)
InstructionOperand DefineAsFixed(turboshaft::OpIndex node, FPRegType reg)
UnallocatedOperand ToDualLocationUnallocatedOperand(LinkageLocation primary_location, LinkageLocation secondary_location, int virtual_register)
InstructionOperand UseRegisterOrSlotOrConstant(turboshaft::OpIndex node)
InstructionOperand DefineSameAsFirst(turboshaft::OpIndex node)
InstructionOperand UseUniqueRegister(turboshaft::OpIndex node)
InstructionOperand UseImmediate(turboshaft::OpIndex node)
InstructionOperand UseUniqueRegisterOrSlotOrConstant(turboshaft::OpIndex node)
InstructionOperand UseImmediate64(int64_t immediate)
InstructionOperand DefineAsConstant(turboshaft::OpIndex node)
OperandGeneratorT(InstructionSelectorT *selector)
InstructionOperand UseUnique(turboshaft::OpIndex node)
int GetVReg(turboshaft::OpIndex node) const
InstructionOperand UseRegisterAtEnd(turboshaft::OpIndex node)
InstructionOperand UseRegister(turboshaft::OpIndex node)
InstructionOperand DefineSameAsInput(turboshaft::OpIndex node, int input_index)
InstructionOperand TempFpRegister(FPRegType reg)
InstructionOperand UseAny(turboshaft::OpIndex node)
InstructionOperand DefineAsFixed(turboshaft::OpIndex node, Register reg)
InstructionOperand DefineAsLocation(turboshaft::OpIndex node, LinkageLocation location)
InstructionOperand TempLocation(LinkageLocation location)
UnallocatedOperand Define(turboshaft::OpIndex node, UnallocatedOperand operand)
InstructionOperand Label(turboshaft::Block *block)
InstructionOperand UseRegisterWithMode(turboshaft::OpIndex node, RegisterMode register_mode)
SwitchInfoT(ZoneVector< CaseInfo > const &cases, int32_t min_value, int32_t max_value, turboshaft::Block *default_branch)
std::vector< CaseInfo > CasesSortedByValue() const
const ZoneVector< CaseInfo > & CasesUnsorted() const
const underlying_operation_t< Op > * TryCast(V< AnyOrNone > op_idx) const
ZoneVector< RpoNumber > & result
LiftoffRegister reg
int r
Definition mul-fft.cc:298
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
bool operator<(const CaseInfoT &l, const CaseInfoT &r)
constexpr int kSystemPointerSize
Definition globals.h:410
constexpr bool IsFloatingPoint(MachineRepresentation rep)
constexpr int kInt32Size
Definition globals.h:401
constexpr bool Is64()
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
RpoNumber rpo_number(const turboshaft::Block *block) const
#define V8_LIKELY(condition)
Definition v8config.h:661