Commit 99385e8e authored by Miran.Karic's avatar Miran.Karic Committed by Commit bot

MIPS: [turbofan] Fix addition for deoptimization.

In turbofan, after an addition operation where the same register is the
output and both inputs, if deoptimization is performed the input is
overwritten with the output value and the final result is not correct.
This is fixed by restoring the original value of the input before
deoptimization.

BUG=
TEST=mjsunit/regress/regress-int32-truncation

Review-Url: https://codereview.chromium.org/2102063002
Cr-Commit-Position: refs/heads/master@{#37524}
parent b18b3877
......@@ -1794,10 +1794,21 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
__ Branch(tlabel, cc, at, Operand(zero_reg));
} else if (instr->arch_opcode() == kMips64Dadd ||
instr->arch_opcode() == kMips64Dsub) {
Label done;
cc = FlagsConditionToConditionOvf(branch->condition);
__ dsra32(kScratchReg, i.OutputRegister(), 0);
__ sra(at, i.OutputRegister(), 31);
__ Branch(tlabel, cc, at, Operand(kScratchReg));
__ Branch(&done, NegateCondition(cc), at, Operand(kScratchReg));
// If we deoptimize, check if output register is the same as input
// registers, if yes input values are overwritten so fix them first.
if (instr->InputAt(1)->IsRegister()) {
if (i.InputRegister(0).is(i.OutputRegister()) &&
i.InputRegister(1).is(i.OutputRegister())) {
__ dsra(i.OutputRegister(), i.OutputRegister(), 1);
}
}
__ Branch(tlabel);
__ bind(&done);
} else if (instr->arch_opcode() == kMips64DaddOvf) {
switch (branch->condition) {
case kOverflow:
......
......@@ -5493,11 +5493,14 @@ void MacroAssembler::AddBranchOvf(Register dst, Register left, Register right,
DCHECK(!right.is(scratch));
if (left.is(right) && dst.is(left)) {
mov(overflow_dst, right);
right = overflow_dst;
}
if (dst.is(left)) {
mov(scratch, left); // Preserve left and right.
addu(dst, left, right); // Both are overwritten.
xor_(overflow_dst, dst, scratch); // Left and right are equal.
Label done; // Restore inputs if overflow.
Branch(&done, ge, overflow_dst, Operand(zero_reg));
mov(left, scratch); // Original left and right.
bind(&done);
} else if (dst.is(left)) {
mov(scratch, left); // Preserve left.
addu(dst, left, right); // Left is overwritten.
xor_(scratch, dst, scratch); // Original left.
......
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