16 InstructionOperand source;
18 bool operator<(
const MoveKey& other)
const {
19 if (this->source != other.source) {
20 return this->source.Compare(other.source);
22 return this->destination.Compare(other.destination);
25 return std::tie(this->source, this->destination) ==
26 std::tie(other.source, other.destination);
32 explicit OperandSet(ZoneVector<InstructionOperand>* buffer)
37 void InsertOp(
const InstructionOperand& op) {
44 bool Contains(
const InstructionOperand& op)
const {
45 for (
const InstructionOperand& elem : *set_) {
46 if (elem.EqualsCanonicalized(op))
return true;
51 bool ContainsOpOrAlias(
const InstructionOperand& op)
const {
52 if (Contains(op))
return true;
82 config->GetAliases(rep, loc.register_code(), other_rep1, &base);
83 DCHECK(aliases > 0 || (aliases == 0 && base == -1));
90 aliases = config->GetAliases(rep, loc.register_code(), other_rep2, &base);
91 DCHECK(aliases > 0 || (aliases == 0 && base == -1));
103 static bool HasMixedFPReps(
int reps) {
107 ZoneVector<InstructionOperand>*
set_;
111int FindFirstNonEmptySlot(
const Instruction*
instr) {
115 if (moves ==
nullptr)
continue;
116 for (MoveOperands* move : *moves) {
117 if (!move->IsRedundant())
return i;
128 : local_zone_(local_zone),
130 local_vector_(local_zone),
131 operand_buffer1(local_zone),
132 operand_buffer2(local_zone) {}
142 if (block->PredecessorCount() <= 1)
continue;
143 if (!block->IsDeferred()) {
144 bool has_only_deferred =
true;
145 for (
RpoNumber& pred_id : block->predecessors()) {
146 if (!
code()->InstructionBlockAt(pred_id)->IsDeferred()) {
147 has_only_deferred =
false;
155 if (has_only_deferred)
continue;
165 if (instruction->IsCall())
return;
167 if (moves ==
nullptr)
return;
169 DCHECK(instruction->parallel_moves()[1] ==
nullptr ||
170 instruction->parallel_moves()[1]->empty());
177 for (
size_t i = 0;
i < instruction->OutputCount(); ++
i) {
178 outputs.InsertOp(*instruction->OutputAt(
i));
180 for (
size_t i = 0;
i < instruction->TempCount(); ++
i) {
181 outputs.InsertOp(*instruction->TempAt(
i));
185 for (
size_t i = 0;
i < instruction->InputCount(); ++
i) {
186 inputs.InsertOp(*instruction->InputAt(
i));
191 if (outputs.ContainsOpOrAlias(move->destination()) &&
192 !inputs.ContainsOpOrAlias(move->destination())) {
199 if (instruction->IsRet() || instruction->IsTailCall()) {
201 if (!inputs.ContainsOpOrAlias(move->destination())) {
209 if (from->IsCall())
return;
212 if (from_moves ==
nullptr || from_moves->empty())
return;
219 for (
size_t i = 0;
i < from->InputCount(); ++
i) {
220 dst_cant_be.InsertOp(*from->InputAt(
i));
228 for (
size_t i = 0;
i < from->OutputCount(); ++
i) {
229 src_cant_be.InsertOp(*from->OutputAt(
i));
231 for (
size_t i = 0;
i < from->TempCount(); ++
i) {
232 src_cant_be.InsertOp(*from->TempAt(
i));
235 if (move->IsRedundant())
continue;
240 src_cant_be.InsertOp(move->destination());
252 if (move->IsRedundant())
continue;
253 if (!dst_cant_be.ContainsOpOrAlias(move->destination())) {
254 MoveKey
key = {move->source(), move->destination()};
258 if (move_candidates.
empty())
return;
261 bool changed =
false;
264 for (
auto iter = move_candidates.
begin(); iter != move_candidates.
end();) {
265 auto [move,
_] = *iter;
266 if (src_cant_be.ContainsOpOrAlias(move.source)) {
267 src_cant_be.InsertOp(move.destination);
268 iter = move_candidates.
erase(iter);
278 if (move->IsRedundant())
continue;
279 MoveKey
key = {move->source(), move->destination()};
280 if (move_candidates.
find(
key) != move_candidates.
end()) {
285 if (to_move.empty())
return;
298 if (right ==
nullptr)
return;
303 if (!left->empty()) {
307 if (move->IsRedundant())
continue;
312 to_eliminate->Eliminate();
318 if (move->IsRedundant())
continue;
319 left->push_back(move);
327 int i = FindFirstNonEmptySlot(instruction);
350 (first !=
nullptr && (last ==
nullptr || last->empty())));
354 int first_instr_index = block->first_instruction_index();
355 int last_instr_index = block->last_instruction_index();
362 for (
int index = first_instr_index + 1; index <= last_instr_index; ++
index) {
381 for (
RpoNumber& pred_index : block->predecessors()) {
391 if (last_instr->
IsCall())
return;
392 if (last_instr->
TempCount() != 0)
return;
396 if (!op->IsConstant() && !op->IsImmediate())
return;
404 size_t correct_counts = 0;
406 for (
RpoNumber& pred_index : block->predecessors()) {
409 if (
instr->parallel_moves()[0] ==
nullptr ||
410 instr->parallel_moves()[0]->empty()) {
414 if (move->IsRedundant())
continue;
417 MoveKey
key = {src, dst};
418 auto [it, inserted] = move_map.
emplace(
key, 1);
421 if (it->second == block->PredecessorCount()) {
427 if (move_map.
empty() || correct_counts == 0)
return;
432 if (correct_counts != move_map.
size()) {
436 for (
auto iter = move_map.
begin(); iter != move_map.
end();) {
437 auto [move,
count] = *iter;
438 if (
count != block->PredecessorCount()) {
443 conflicting_srcs.InsertOp(move.destination);
444 iter = move_map.
erase(iter);
450 bool changed =
false;
455 for (
auto iter = move_map.
begin(); iter != move_map.
end();) {
456 auto [move,
count] = *iter;
459 if (conflicting_srcs.ContainsOpOrAlias(move.source)) {
460 conflicting_srcs.InsertOp(move.destination);
461 iter = move_map.
erase(iter);
470 if (move_map.
empty())
return;
473 bool gap_initialized =
true;
474 if (
instr->parallel_moves()[0] !=
nullptr &&
475 !
instr->parallel_moves()[0]->empty()) {
477 gap_initialized =
false;
478 std::swap(
instr->parallel_moves()[0],
instr->parallel_moves()[1]);
483 bool first_iteration =
true;
484 for (
RpoNumber& pred_index : block->predecessors()) {
487 if (move->IsRedundant())
continue;
488 MoveKey
key = {move->source(), move->destination()};
490 if (it != move_map.
end()) {
491 if (first_iteration) {
492 moves->
AddMove(move->source(), move->destination());
497 first_iteration =
false;
500 if (!gap_initialized) {
512bool Is64BitsWide(
const InstructionOperand& op) {
514#if V8_COMPRESS_POINTERS
526bool LoadCompare(
const MoveOperands* a,
const MoveOperands* b) {
527 if (!a->source().EqualsCanonicalized(b->source())) {
528 return a->source().CompareCanonicalized(b->source());
533 if (a->destination().IsLocationOperand() &&
534 b->destination().IsLocationOperand()) {
535 if (Is64BitsWide(a->destination()) && !Is64BitsWide(b->destination())) {
538 if (!Is64BitsWide(a->destination()) && Is64BitsWide(b->destination())) {
542 if (IsSlot(a->destination()) && !IsSlot(b->destination()))
return false;
543 if (!IsSlot(a->destination()) && IsSlot(b->destination()))
return true;
544 return a->destination().CompareCanonicalized(b->destination());
556 if (parallel_moves ==
nullptr)
return;
559 if (move->IsRedundant())
continue;
560 if (move->source().IsConstant() || IsSlot(move->source())) {
564 if (loads.
empty())
return;
567 std::sort(loads.
begin(), loads.
end(), LoadCompare);
571 if (group_begin ==
nullptr ||
572 !load->
source().EqualsCanonicalized(group_begin->
source())) {
std::pair< iterator, bool > emplace(Args &&... args)
iterator erase(const iterator &position)
iterator find(const key_type &key)
static const RegisterConfiguration * Default()
void push_back(const T &value)
int last_instruction_index() const
size_t SuccessorCount() const
bool IsFPStackSlot() const
InstructionBlock * InstructionBlockAt(RpoNumber rpo_number)
const Instructions & instructions() const
const InstructionOperand * InputAt(size_t i) const
size_t OutputCount() const
ParallelMove *const * parallel_moves() const
size_t InputCount() const
MachineRepresentation representation() const
static LocationOperand * cast(InstructionOperand *op)
const InstructionOperand & source() const
const InstructionOperand & destination() const
void CompressGaps(Instruction *instr)
ZoneVector< InstructionOperand > operand_buffer2
void CompressBlock(InstructionBlock *block)
void MigrateMoves(Instruction *to, Instruction *from)
void FinalizeMoves(Instruction *instr)
void CompressMoves(ParallelMove *left, MoveOpVector *right)
void OptimizeMerge(InstructionBlock *block)
MoveOpVector & local_vector()
Zone * local_zone() const
MoveOptimizer(Zone *local_zone, InstructionSequence *code)
ZoneVector< InstructionOperand > operand_buffer1
InstructionSequence * code() const
void RemoveClobberedDestinations(Instruction *instruction)
const Instruction * LastInstruction(const InstructionBlock *block) const
void PrepareInsertAfter(MoveOperands *move, ZoneVector< MoveOperands * > *to_eliminate) const
MoveOperands * AddMove(const InstructionOperand &from, const InstructionOperand &to)
ZoneList< RegExpInstruction > code_
ZoneVector< InstructionOperand > * set_
InstructionOperand destination
constexpr bool IsPowerOfTwo(T value)
bool operator<(const CaseInfoT &l, const CaseInfoT &r)
bool operator==(const BranchParameters &lhs, const BranchParameters &rhs)
constexpr AliasingKind kFPAliasing
V8_EXPORT_PRIVATE constexpr int RepresentationBit(MachineRepresentation rep)
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)