[maglev] Fix deopt condition in Int32Div
1. A remainder equal to zero means no deopt. 2. We need the input value in the input register, so we need to treat rax as a clobbered temporary instead of a fixed input. Bug: v8:7700 Change-Id: I9a7b7f3cc48e17b262aa7f9084fa864ad505be54 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3788099 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Auto-Submit: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#82044}
This commit is contained in:
parent
04483dbb2c
commit
c34c85a53b
@ -1701,24 +1701,29 @@ void Int32MultiplyWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
|
||||
void Int32DivideWithOverflow::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseFixed(left_input(), rax);
|
||||
UseRegister(left_input());
|
||||
UseRegister(right_input());
|
||||
DefineAsFixed(vreg_state, this, rax);
|
||||
// rdx is clobbered by idiv.
|
||||
// rax,rdx are clobbered by idiv.
|
||||
RequireSpecificTemporary(rax);
|
||||
RequireSpecificTemporary(rdx);
|
||||
}
|
||||
|
||||
void Int32DivideWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
DCHECK_EQ(rax, ToRegister(left_input()));
|
||||
DCHECK(temporaries().has(rax));
|
||||
DCHECK(temporaries().has(rdx));
|
||||
Register left = ToRegister(left_input());
|
||||
Register right = ToRegister(right_input());
|
||||
__ movl(rax, left);
|
||||
// Clear rdx so that it doesn't participate in the division.
|
||||
__ xorl(rdx, rdx);
|
||||
// TODO(leszeks): peephole optimise division by a constant.
|
||||
__ idivl(right);
|
||||
__ cmpl(rdx, Immediate(0));
|
||||
EmitEagerDeoptIf(equal, code_gen_state, DeoptimizeReason::kNotInt32, this);
|
||||
EmitEagerDeoptIf(not_equal, code_gen_state, DeoptimizeReason::kNotInt32,
|
||||
this);
|
||||
DCHECK_EQ(ToRegister(result()), rax);
|
||||
}
|
||||
|
||||
void Int32BitwiseAnd::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
|
@ -460,6 +460,17 @@ void StraightForwardRegisterAllocator::UpdateUse(
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
namespace {
|
||||
Register GetNodeResultRegister(Node* node) {
|
||||
ValueNode* value_node = node->TryCast<ValueNode>();
|
||||
if (!value_node) return Register::no_reg();
|
||||
if (!value_node->result().operand().IsRegister()) return Register::no_reg();
|
||||
return value_node->result().AssignedGeneralRegister();
|
||||
}
|
||||
} // namespace
|
||||
#endif // DEBUG
|
||||
|
||||
void StraightForwardRegisterAllocator::AllocateNode(Node* node) {
|
||||
current_node_ = node;
|
||||
if (FLAG_trace_maglev_regalloc) {
|
||||
@ -507,7 +518,11 @@ void StraightForwardRegisterAllocator::AllocateNode(Node* node) {
|
||||
printing_visitor_->os() << "\n";
|
||||
}
|
||||
|
||||
DCHECK_EQ(general_registers_.free() | node->temporaries(),
|
||||
// All the temporaries should be free by the end. The exception is the node
|
||||
// result, which could be written into a register that was previously
|
||||
// considered a temporary.
|
||||
DCHECK_EQ(general_registers_.free() |
|
||||
(node->temporaries() - GetNodeResultRegister(node)),
|
||||
general_registers_.free());
|
||||
general_registers_.clear_blocked();
|
||||
double_registers_.clear_blocked();
|
||||
|
Loading…
Reference in New Issue
Block a user