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:
parent
b18b387795
commit
99385e8e4b
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user