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}
This commit is contained in:
Miran.Karic 2016-07-05 04:23:17 -07:00 committed by Commit bot
parent b18b387795
commit 99385e8e4b
2 changed files with 20 additions and 6 deletions

View File

@ -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:

View File

@ -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.