Commit ef546d68 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[turbofan, ia32] Fix moves from constant to poison register.

This makes the moves from constants to the poisoning register
explicit so that the register allocator does not have to burn
a register on it.

Bug: chromium:798964, chromium:820726, v8:7503, v8:7518
Change-Id: Ifc8f9a2f685405dd38fec583bb0e20c3f0320903
Reviewed-on: https://chromium-review.googlesource.com/964202Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51963}
parent fda0d684
......@@ -294,9 +294,9 @@ void MoveOperandIfAliasedWithPoisonRegister(Instruction* call_instruction,
return;
}
if (HasImmediateInput(call_instruction, poison_index)) {
gen->tasm()->mov(kSpeculationPoisonRegister,
i.InputImmediate(poison_index));
InstructionOperand* op = call_instruction->InputAt(poison_index);
if (op->IsImmediate() || op->IsConstant()) {
gen->tasm()->mov(kSpeculationPoisonRegister, i.ToImmediate(op));
} else {
gen->tasm()->mov(kSpeculationPoisonRegister, i.InputOperand(poison_index));
}
......
......@@ -128,17 +128,23 @@ class OperandGenerator {
}
InstructionOperand UseAnyAtEnd(Node* node) {
return Use(node, UnallocatedOperand(UnallocatedOperand::ANY,
return Use(node, UnallocatedOperand(UnallocatedOperand::REGISTER_OR_SLOT,
UnallocatedOperand::USED_AT_END,
GetVReg(node)));
}
InstructionOperand UseAny(Node* node) {
return Use(node, UnallocatedOperand(UnallocatedOperand::ANY,
return Use(node, UnallocatedOperand(UnallocatedOperand::REGISTER_OR_SLOT,
UnallocatedOperand::USED_AT_START,
GetVReg(node)));
}
InstructionOperand UseRegisterOrSlotOrConstant(Node* node) {
return Use(node, UnallocatedOperand(
UnallocatedOperand::REGISTER_OR_SLOT_OR_CONSTANT,
UnallocatedOperand::USED_AT_START, GetVReg(node)));
}
InstructionOperand UseRegister(Node* node) {
return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
UnallocatedOperand::USED_AT_START,
......
......@@ -1000,7 +1000,7 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
if (reg == kSpeculationPoisonRegister.code()) {
buffer->instruction_args[poison_alias_index] = g.TempImmediate(
static_cast<int32_t>(buffer->instruction_args.size()));
op = g.Use(*iter);
op = g.UseRegisterOrSlotOrConstant(*iter);
}
}
buffer->instruction_args.push_back(op);
......
......@@ -156,8 +156,10 @@ std::ostream& operator<<(std::ostream& os,
return os << "(S)";
case UnallocatedOperand::SAME_AS_FIRST_INPUT:
return os << "(1)";
case UnallocatedOperand::ANY:
case UnallocatedOperand::REGISTER_OR_SLOT:
return os << "(-)";
case UnallocatedOperand::REGISTER_OR_SLOT_OR_CONSTANT:
return os << "(*)";
}
}
case InstructionOperand::CONSTANT:
......
......@@ -170,7 +170,8 @@ class UnallocatedOperand final : public InstructionOperand {
enum ExtendedPolicy {
NONE,
ANY,
REGISTER_OR_SLOT,
REGISTER_OR_SLOT_OR_CONSTANT,
FIXED_REGISTER,
FIXED_FP_REGISTER,
MUST_HAVE_REGISTER,
......@@ -236,8 +237,13 @@ class UnallocatedOperand final : public InstructionOperand {
}
// Predicates for the operand policy.
bool HasAnyPolicy() const {
return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
bool HasRegisterOrSlotPolicy() const {
return basic_policy() == EXTENDED_POLICY &&
extended_policy() == REGISTER_OR_SLOT;
}
bool HasRegisterOrSlotOrConstantPolicy() const {
return basic_policy() == EXTENDED_POLICY &&
extended_policy() == REGISTER_OR_SLOT_OR_CONSTANT;
}
bool HasFixedPolicy() const {
return basic_policy() == FIXED_SLOT ||
......
......@@ -167,14 +167,18 @@ void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op,
constraint->value_ = unallocated->fixed_slot_index();
} else {
switch (unallocated->extended_policy()) {
case UnallocatedOperand::ANY:
case UnallocatedOperand::REGISTER_OR_SLOT:
case UnallocatedOperand::NONE:
if (sequence()->IsFP(vreg)) {
constraint->type_ = kNoneFP;
constraint->type_ = kRegisterOrSlotFP;
} else {
constraint->type_ = kNone;
constraint->type_ = kRegisterOrSlot;
}
break;
case UnallocatedOperand::REGISTER_OR_SLOT_OR_CONSTANT:
DCHECK(!sequence()->IsFP(vreg));
constraint->type_ = kRegisterOrSlotOrConstant;
break;
case UnallocatedOperand::FIXED_REGISTER:
if (unallocated->HasSecondaryStorage()) {
constraint->type_ = kRegisterAndSlot;
......@@ -252,12 +256,16 @@ void RegisterAllocatorVerifier::CheckConstraint(
CHECK_EQ(ElementSizeLog2Of(LocationOperand::cast(op)->representation()),
constraint->value_);
return;
case kNone:
case kRegisterOrSlot:
CHECK_WITH_MSG(op->IsRegister() || op->IsStackSlot(), caller_info_);
return;
case kNoneFP:
case kRegisterOrSlotFP:
CHECK_WITH_MSG(op->IsFPRegister() || op->IsFPStackSlot(), caller_info_);
return;
case kRegisterOrSlotOrConstant:
CHECK_WITH_MSG(op->IsRegister() || op->IsStackSlot() || op->IsConstant(),
caller_info_);
return;
case kSameAsFirst:
CHECK_WITH_MSG(false, caller_info_);
return;
......
......@@ -185,8 +185,9 @@ class RegisterAllocatorVerifier final : public ZoneObject {
kFixedFPRegister,
kSlot,
kFixedSlot,
kNone,
kNoneFP,
kRegisterOrSlot,
kRegisterOrSlotFP,
kRegisterOrSlotOrConstant,
kExplicit,
kSameAsFirst,
kRegisterAndSlot
......
......@@ -261,7 +261,7 @@ UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand,
: operand_(operand), hint_(hint), next_(nullptr), pos_(pos), flags_(0) {
DCHECK_IMPLIES(hint == nullptr, hint_type == UsePositionHintType::kNone);
bool register_beneficial = true;
UsePositionType type = UsePositionType::kAny;
UsePositionType type = UsePositionType::kRegisterOrSlot;
if (operand_ != nullptr && operand_->IsUnallocated()) {
const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_);
if (unalloc->HasRegisterPolicy()) {
......@@ -269,8 +269,11 @@ UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand,
} else if (unalloc->HasSlotPolicy()) {
type = UsePositionType::kRequiresSlot;
register_beneficial = false;
} else if (unalloc->HasRegisterOrSlotOrConstantPolicy()) {
type = UsePositionType::kRegisterOrSlotOrConstant;
register_beneficial = false;
} else {
register_beneficial = !unalloc->HasAnyPolicy();
register_beneficial = !unalloc->HasRegisterOrSlotPolicy();
}
}
flags_ = TypeField::encode(type) | HintTypeField::encode(hint_type) |
......@@ -714,7 +717,8 @@ void LiveRange::ConvertUsesToOperand(const InstructionOperand& op,
case UsePositionType::kRequiresRegister:
DCHECK(op.IsRegister() || op.IsFPRegister());
V8_FALLTHROUGH;
case UsePositionType::kAny:
case UsePositionType::kRegisterOrSlot:
case UsePositionType::kRegisterOrSlotOrConstant:
InstructionOperand::ReplaceWith(pos->operand(), &op);
break;
}
......@@ -748,7 +752,8 @@ void LiveRange::SetUseHints(int register_index) {
case UsePositionType::kRequiresSlot:
break;
case UsePositionType::kRequiresRegister:
case UsePositionType::kAny:
case UsePositionType::kRegisterOrSlot:
case UsePositionType::kRegisterOrSlotOrConstant:
pos->set_assigned_register(register_index);
break;
}
......@@ -1674,7 +1679,8 @@ void ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock(
int gap_index = successor->first_instruction_index();
// Create an unconstrained operand for the same virtual register
// and insert a gap move from the fixed output to the operand.
UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
UnallocatedOperand output_copy(UnallocatedOperand::REGISTER_OR_SLOT,
output_vreg);
data()->AddGapMove(gap_index, Instruction::START, *output, output_copy);
}
}
......@@ -1715,7 +1721,8 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
bool assigned = false;
if (first_output->HasFixedPolicy()) {
int output_vreg = first_output->virtual_register();
UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
UnallocatedOperand output_copy(UnallocatedOperand::REGISTER_OR_SLOT,
output_vreg);
bool is_tagged = code()->IsReference(output_vreg);
if (first_output->HasSecondaryStorage()) {
range->MarkHasPreassignedSlot();
......@@ -1757,7 +1764,8 @@ void ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
UnallocatedOperand* cur_input = UnallocatedOperand::cast(input);
if (cur_input->HasFixedPolicy()) {
int input_vreg = cur_input->virtual_register();
UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg);
UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT,
input_vreg);
bool is_tagged = code()->IsReference(input_vreg);
AllocateFixed(cur_input, instr_index, is_tagged);
data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input);
......@@ -1774,7 +1782,8 @@ void ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
UnallocatedOperand::cast(second->InputAt(0));
int output_vreg = second_output->virtual_register();
int input_vreg = cur_input->virtual_register();
UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg);
UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT,
input_vreg);
*cur_input =
UnallocatedOperand(*cur_input, second_output->virtual_register());
MoveOperands* gap_move = data()->AddGapMove(instr_index, Instruction::END,
......@@ -1816,7 +1825,8 @@ void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) {
for (size_t i = 0; i < phi->operands().size(); ++i) {
InstructionBlock* cur_block =
code()->InstructionBlockAt(block->predecessors()[i]);
UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]);
UnallocatedOperand input(UnallocatedOperand::REGISTER_OR_SLOT,
phi->operands()[i]);
MoveOperands* move = data()->AddGapMove(
cur_block->last_instruction_index(), Instruction::END, input, output);
map_value->AddOperand(&move->destination());
......@@ -2410,8 +2420,11 @@ void LiveRangeBuilder::BuildLiveRanges() {
if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) {
for (UsePosition* pos = range->first_pos(); pos != nullptr;
pos = pos->next()) {
if (pos->type() == UsePositionType::kRequiresSlot) continue;
UsePositionType new_type = UsePositionType::kAny;
if (pos->type() == UsePositionType::kRequiresSlot ||
pos->type() == UsePositionType::kRegisterOrSlotOrConstant) {
continue;
}
UsePositionType new_type = UsePositionType::kRegisterOrSlot;
// Can't mark phis as needing a register.
if (!pos->pos().IsGapPosition()) {
new_type = UsePositionType::kRequiresRegister;
......
......@@ -229,9 +229,12 @@ class UseInterval final : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(UseInterval);
};
enum class UsePositionType : uint8_t { kAny, kRequiresRegister, kRequiresSlot };
enum class UsePositionType : uint8_t {
kRegisterOrSlot,
kRegisterOrSlotOrConstant,
kRequiresRegister,
kRequiresSlot
};
enum class UsePositionHintType : uint8_t {
kNone,
......
......@@ -83,7 +83,7 @@ class InstructionTester : public HandleAndZoneScope {
}
UnallocatedOperand Unallocated(int vreg) {
return UnallocatedOperand(UnallocatedOperand::ANY, vreg);
return UnallocatedOperand(UnallocatedOperand::REGISTER_OR_SLOT, vreg);
}
RpoNumber RpoFor(BasicBlock* block) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment