1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/gap-resolver.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <algorithm> 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <functional> 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <set> 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace { 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 17c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#define REP_BIT(rep) (1 << static_cast<int>(rep)) 18c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 19c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochconst int kFloat32Bit = REP_BIT(MachineRepresentation::kFloat32); 20c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochconst int kFloat64Bit = REP_BIT(MachineRepresentation::kFloat64); 21c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline bool Blocks(MoveOperands* move, InstructionOperand destination) { 23c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return !move->IsEliminated() && move->source().InterferesWith(destination); 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Splits a FP move between two location operands into the equivalent series of 27c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// moves between smaller sub-operands, e.g. a double move to two single moves. 28c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// This helps reduce the number of cycles that would normally occur under FP 29c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// aliasing, and makes swaps much easier to implement. 30c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochMoveOperands* Split(MoveOperands* move, MachineRepresentation smaller_rep, 31c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ParallelMove* moves) { 32c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(!kSimpleFPAliasing); 33c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Splitting is only possible when the slot size is the same as float size. 34c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(kPointerSize, kFloatSize); 35c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const LocationOperand& src_loc = LocationOperand::cast(move->source()); 36c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const LocationOperand& dst_loc = LocationOperand::cast(move->destination()); 37c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MachineRepresentation dst_rep = dst_loc.representation(); 38c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_NE(smaller_rep, dst_rep); 39c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto src_kind = src_loc.location_kind(); 40c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto dst_kind = dst_loc.location_kind(); 41c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 42c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int aliases = 43c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1 << (ElementSizeLog2Of(dst_rep) - ElementSizeLog2Of(smaller_rep)); 44c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int base = -1; 45c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch USE(base); 46c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(aliases, RegisterConfiguration::Turbofan()->GetAliases( 47c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch dst_rep, 0, smaller_rep, &base)); 48c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 49c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int src_index = -1; 50c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int slot_size = (1 << ElementSizeLog2Of(smaller_rep)) / kPointerSize; 51c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int src_step = 1; 52c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (src_kind == LocationOperand::REGISTER) { 53c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch src_index = src_loc.register_code() * aliases; 54c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 55c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch src_index = src_loc.index(); 56c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // For operands that occuply multiple slots, the index refers to the last 57c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // slot. On little-endian architectures, we start at the high slot and use a 58c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // negative step so that register-to-slot moves are in the correct order. 59c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch src_step = -slot_size; 60c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 61c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int dst_index = -1; 62c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int dst_step = 1; 63c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (dst_kind == LocationOperand::REGISTER) { 64c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch dst_index = dst_loc.register_code() * aliases; 65c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 66c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch dst_index = dst_loc.index(); 67c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch dst_step = -slot_size; 68c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Reuse 'move' for the first fragment. It is not pending. 71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch move->set_source(AllocatedOperand(src_kind, smaller_rep, src_index)); 72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch move->set_destination(AllocatedOperand(dst_kind, smaller_rep, dst_index)); 73c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Add the remaining fragment moves. 74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (int i = 1; i < aliases; ++i) { 75c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch src_index += src_step; 76c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch dst_index += dst_step; 77c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch moves->AddMove(AllocatedOperand(src_kind, smaller_rep, src_index), 78c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AllocatedOperand(dst_kind, smaller_rep, dst_index)); 79c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 80c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Return the first fragment. 81c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return move; 82c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid GapResolver::Resolve(ParallelMove* moves) { 87c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Clear redundant moves, and collect FP move representations if aliasing 88c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // is non-simple. 89c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int reps = 0; 90c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (size_t i = 0; i < moves->size();) { 91c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch MoveOperands* move = (*moves)[i]; 92c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (move->IsRedundant()) { 93c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (*moves)[i] = moves->back(); 94c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch moves->pop_back(); 95c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch continue; 96c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 97c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch i++; 98c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!kSimpleFPAliasing && move->destination().IsFPRegister()) { 99c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch reps |= 100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch REP_BIT(LocationOperand::cast(move->destination()).representation()); 101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!kSimpleFPAliasing) { 105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (reps && !base::bits::IsPowerOfTwo32(reps)) { 106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Start with the smallest FP moves, so we never encounter smaller moves 107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // in the middle of a cycle of larger moves. 108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if ((reps & kFloat32Bit) != 0) { 109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch split_rep_ = MachineRepresentation::kFloat32; 110c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (size_t i = 0; i < moves->size(); ++i) { 111c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto move = (*moves)[i]; 112c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!move->IsEliminated() && move->destination().IsFloatRegister()) 113c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch PerformMove(moves, move); 114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if ((reps & kFloat64Bit) != 0) { 117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch split_rep_ = MachineRepresentation::kFloat64; 118c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (size_t i = 0; i < moves->size(); ++i) { 119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto move = (*moves)[i]; 120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!move->IsEliminated() && move->destination().IsDoubleRegister()) 121c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch PerformMove(moves, move); 122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 123c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 125c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch split_rep_ = MachineRepresentation::kSimd128; 126c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 128c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (size_t i = 0; i < moves->size(); ++i) { 129c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto move = (*moves)[i]; 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!move->IsEliminated()) PerformMove(moves, move); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid GapResolver::PerformMove(ParallelMove* moves, MoveOperands* move) { 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Each call to this function performs a move and deletes it from the move 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // graph. We first recursively perform any move blocking this one. We mark a 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // move as "pending" on entry to PerformMove in order to detect cycles in the 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // move graph. We use operand swaps to resolve cycles, which means that a 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call to PerformMove could change any source operand in the move graph. 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!move->IsPending()); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!move->IsRedundant()); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clear this move's destination to indicate a pending move. The actual 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // destination is saved on the side. 145c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch InstructionOperand source = move->source(); 146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(!source.IsInvalid()); // Or else it will look eliminated. 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InstructionOperand destination = move->destination(); 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch move->SetPending(); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We may need to split moves between FP locations differently. 151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool is_fp_loc_move = !kSimpleFPAliasing && destination.IsFPLocationOperand(); 152c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform a depth-first traversal of the move graph to resolve dependencies. 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Any unperformed, unpending move with a source the same as this one's 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // destination blocks this one so recursively perform all such moves. 156c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (size_t i = 0; i < moves->size(); ++i) { 157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto other = (*moves)[i]; 158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (other->IsEliminated()) continue; 159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (other->IsPending()) continue; 160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (other->source().InterferesWith(destination)) { 161c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!kSimpleFPAliasing && is_fp_loc_move && 162c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch LocationOperand::cast(other->source()).representation() > 163c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch split_rep_) { 164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 'other' must also be an FP location move. Break it into fragments 165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // of the same size as 'move'. 'other' is set to one of the fragments, 166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // and the rest are appended to 'moves'. 167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch other = Split(other, split_rep_, moves); 168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // 'other' may not block destination now. 169c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!other->source().InterferesWith(destination)) continue; 170c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Though PerformMove can change any source operand in the move graph, 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this call cannot create a blocking move via a swap (this loop does not 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // miss any). Assume there is a non-blocking move with source A and this 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // move is blocked on source B and there is a swap of A and B. Then A and 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // B must be involved in the same cycle (or they would not be swapped). 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since this move's destination is B and there is only a single incoming 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // edge to an operand, this move must also be involved in the same cycle. 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In that case, the blocking move will be created but will be "pending" 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // when we return from PerformMove. 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PerformMove(moves, other); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This move's source may have changed due to swaps to resolve cycles and so 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it may now be the last move in the cycle. If so remove it. 186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch source = move->source(); 187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (source.EqualsCanonicalized(destination)) { 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch move->Eliminate(); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We are about to resolve this move and don't need it marked as pending, so 193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // restore its destination. 194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch move->set_destination(destination); 195c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The move may be blocked on a (at most one) pending move, in which case we 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // have a cycle. Search for such a blocking move and perform a swap to 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // resolve it. 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch auto blocker = std::find_if(moves->begin(), moves->end(), 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch std::bind2nd(std::ptr_fun(&Blocks), destination)); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (blocker == moves->end()) { 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The easy case: This move is not blocked. 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assembler_->AssembleMove(&source, &destination); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch move->Eliminate(); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Ensure source is a register or both are stack slots, to limit swap cases. 209bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (source.IsStackSlot() || source.IsFPStackSlot()) { 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::swap(source, destination); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assembler_->AssembleSwap(&source, &destination); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch move->Eliminate(); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Update outstanding moves whose source may now have been moved. 216c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!kSimpleFPAliasing && is_fp_loc_move) { 217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // We may have to split larger moves. 218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (size_t i = 0; i < moves->size(); ++i) { 219c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto other = (*moves)[i]; 220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (other->IsEliminated()) continue; 221c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (source.InterferesWith(other->source())) { 222c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (LocationOperand::cast(other->source()).representation() > 223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch split_rep_) { 224c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch other = Split(other, split_rep_, moves); 225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!source.InterferesWith(other->source())) continue; 226c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 227c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch other->set_source(destination); 228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else if (destination.InterferesWith(other->source())) { 229c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (LocationOperand::cast(other->source()).representation() > 230c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch split_rep_) { 231c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch other = Split(other, split_rep_, moves); 232c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!destination.InterferesWith(other->source())) continue; 233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 234c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch other->set_source(source); 235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 236c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 237c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 238c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (auto other : *moves) { 239c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (other->IsEliminated()) continue; 240c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (source.EqualsCanonicalized(other->source())) { 241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch other->set_source(destination); 242c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else if (destination.EqualsCanonicalized(other->source())) { 243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch other->set_source(source); 244c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace compiler 249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 251