Commit 21b331e3 authored by balazs.kilvady's avatar balazs.kilvady Committed by Commit bot

MIPS: Use BOVC/BNVC for overflow checking on r6.

BUG=

Review URL: https://codereview.chromium.org/1434263003

Cr-Commit-Position: refs/heads/master@{#32630}
parent 0f2ed07f
......@@ -299,19 +299,6 @@ Condition FlagsConditionToConditionTst(FlagsCondition condition) {
}
Condition FlagsConditionToConditionOvf(FlagsCondition condition) {
switch (condition) {
case kOverflow:
return lt;
case kNotOverflow:
return ge;
default:
break;
}
UNREACHABLE();
return kNoCondition;
}
FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
FlagsCondition condition) {
switch (condition) {
......@@ -627,15 +614,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsAddOvf:
__ AdduAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), kCompareReg, kScratchReg);
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
break;
case kMipsSub:
__ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsSubOvf:
__ SubuAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), kCompareReg, kScratchReg);
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
break;
case kMipsMul:
__ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
......@@ -1122,11 +1107,34 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
cc = FlagsConditionToConditionTst(branch->condition);
__ And(at, i.InputRegister(0), i.InputOperand(1));
__ Branch(tlabel, cc, at, Operand(zero_reg));
} else if (instr->arch_opcode() == kMipsAddOvf ||
instr->arch_opcode() == kMipsSubOvf) {
// kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow.
cc = FlagsConditionToConditionOvf(branch->condition);
__ Branch(tlabel, cc, kCompareReg, Operand(zero_reg));
} else if (instr->arch_opcode() == kMipsAddOvf) {
switch (branch->condition) {
case kOverflow:
__ AddBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel);
break;
case kNotOverflow:
__ AddBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel);
break;
default:
UNSUPPORTED_COND(kMipsAddOvf, branch->condition);
break;
}
} else if (instr->arch_opcode() == kMipsSubOvf) {
switch (branch->condition) {
case kOverflow:
__ SubBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel);
break;
case kNotOverflow:
__ SubBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel);
break;
default:
UNSUPPORTED_COND(kMipsAddOvf, branch->condition);
break;
}
} else if (instr->arch_opcode() == kMipsCmp) {
cc = FlagsConditionToConditionCmp(branch->condition);
__ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1));
......@@ -1193,13 +1201,26 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
return;
} else if (instr->arch_opcode() == kMipsAddOvf ||
instr->arch_opcode() == kMipsSubOvf) {
// kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow.
cc = FlagsConditionToConditionOvf(condition);
// Return 1 on overflow.
__ Slt(result, kCompareReg, Operand(zero_reg));
if (cc == ge) // Invert result on not overflow.
__ xori(result, result, 1);
return;
Label flabel, tlabel;
switch (instr->arch_opcode()) {
case kMipsAddOvf:
__ AddBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), &flabel);
break;
case kMipsSubOvf:
__ SubBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), &flabel);
break;
default:
UNREACHABLE();
break;
}
__ li(result, 1);
__ Branch(&tlabel);
__ bind(&flabel);
__ li(result, 0);
__ bind(&tlabel);
} else if (instr->arch_opcode() == kMipsCmp) {
cc = FlagsConditionToConditionCmp(condition);
switch (cc) {
......
......@@ -1376,9 +1376,10 @@ void LCodeGen::DoMulI(LMulI* instr) {
switch (constant) {
case -1:
if (overflow) {
__ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch,
Operand(zero_reg));
Label no_overflow;
__ SubBranchNoOvf(result, zero_reg, Operand(left), &no_overflow);
DeoptimizeIf(al, instr);
__ bind(&no_overflow);
} else {
__ Subu(result, zero_reg, left);
}
......@@ -1604,21 +1605,19 @@ void LCodeGen::DoSubI(LSubI* instr) {
__ Subu(ToRegister(result), ToRegister(left), ToOperand(right));
}
} else { // can_overflow.
Register overflow = scratch0();
Register scratch = scratch1();
Register scratch = scratch0();
Label no_overflow_label;
if (right->IsStackSlot()) {
Register right_reg = EmitLoadRegister(right, scratch);
__ SubuAndCheckForOverflow(ToRegister(result),
ToRegister(left),
right_reg,
overflow); // Reg at also used as scratch.
__ SubBranchNoOvf(ToRegister(result), ToRegister(left),
Operand(right_reg), &no_overflow_label);
} else {
DCHECK(right->IsRegister() || right->IsConstantOperand());
__ SubuAndCheckForOverflow(ToRegister(result), ToRegister(left),
ToOperand(right), overflow, scratch);
__ SubBranchNoOvf(ToRegister(result), ToRegister(left), ToOperand(right),
&no_overflow_label, scratch);
}
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
Operand(zero_reg));
DeoptimizeIf(al, instr);
__ bind(&no_overflow_label);
}
}
......@@ -1800,21 +1799,19 @@ void LCodeGen::DoAddI(LAddI* instr) {
__ Addu(ToRegister(result), ToRegister(left), ToOperand(right));
}
} else { // can_overflow.
Register overflow = scratch0();
Register scratch = scratch1();
Label no_overflow_label;
if (right->IsStackSlot()) {
Register right_reg = EmitLoadRegister(right, scratch);
__ AdduAndCheckForOverflow(ToRegister(result),
ToRegister(left),
right_reg,
overflow); // Reg at also used as scratch.
__ AddBranchNoOvf(ToRegister(result), ToRegister(left),
Operand(right_reg), &no_overflow_label);
} else {
DCHECK(right->IsRegister() || right->IsConstantOperand());
__ AdduAndCheckForOverflow(ToRegister(result), ToRegister(left),
ToOperand(right), overflow, scratch);
__ AddBranchNoOvf(ToRegister(result), ToRegister(left), ToOperand(right),
&no_overflow_label, scratch);
}
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
Operand(zero_reg));
DeoptimizeIf(al, instr);
__ bind(&no_overflow_label);
}
}
......
......@@ -2282,12 +2282,10 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
break;
}
case Token::ADD:
__ AdduAndCheckForOverflow(v0, left, right, scratch1);
__ BranchOnOverflow(&stub_call, scratch1);
__ AddBranchOvf(v0, left, Operand(right), &stub_call);
break;
case Token::SUB:
__ SubuAndCheckForOverflow(v0, left, right, scratch1);
__ BranchOnOverflow(&stub_call, scratch1);
__ SubBranchOvf(v0, left, Operand(right), &stub_call);
break;
case Token::MUL: {
__ SmiUntag(scratch1, right);
......@@ -3907,8 +3905,7 @@ void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
__ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
__ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout);
__ lw(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
__ AdduAndCheckForOverflow(string_length, string_length, scratch1, scratch3);
__ BranchOnOverflow(&bailout, scratch3);
__ AddBranchOvf(string_length, string_length, Operand(scratch1), &bailout);
__ Branch(&loop, lt, element, Operand(elements_end));
// If array_length is 1, return elements[0], a string.
......@@ -3941,8 +3938,7 @@ void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
__ Branch(&bailout, ne, scratch3, Operand(zero_reg));
__ And(scratch3, scratch2, Operand(0x80000000));
__ Branch(&bailout, ne, scratch3, Operand(zero_reg));
__ AdduAndCheckForOverflow(string_length, string_length, scratch2, scratch3);
__ BranchOnOverflow(&bailout, scratch3);
__ AddBranchOvf(string_length, string_length, Operand(scratch2), &bailout);
__ SmiUntag(string_length);
// Bailout for large object allocations.
......@@ -4408,10 +4404,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
Register scratch1 = a1;
Register scratch2 = t0;
__ li(scratch1, Operand(Smi::FromInt(count_value)));
__ AdduAndCheckForOverflow(v0, v0, scratch1, scratch2);
__ BranchOnNoOverflow(&done, scratch2);
__ AddBranchNoOvf(v0, v0, Operand(scratch1), &done);
// Call stub. Undo operation first.
__ Move(v0, a0);
__ jmp(&stub_call);
......
......@@ -1336,17 +1336,23 @@ void Assembler::bne(Register rs, Register rt, int16_t offset) {
void Assembler::bovc(Register rs, Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rs.is(zero_reg)));
DCHECK(rs.code() >= rt.code());
GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
DCHECK(!rs.is(zero_reg));
if (rs.code() >= rt.code()) {
GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
} else {
GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
}
}
void Assembler::bnvc(Register rs, Register rt, int16_t offset) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rs.is(zero_reg)));
DCHECK(rs.code() >= rt.code());
GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
DCHECK(!rs.is(zero_reg));
if (rs.code() >= rt.code()) {
GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
} else {
GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
}
}
......
This diff is collapsed.
......@@ -1188,46 +1188,43 @@ class MacroAssembler: public Assembler {
// Usage: first call the appropriate arithmetic function, then call one of the
// jump functions with the overflow_dst register as the second parameter.
void AdduAndCheckForOverflow(Register dst,
Register left,
Register right,
Register overflow_dst,
Register scratch = at);
void AdduAndCheckForOverflow(Register dst, Register left,
const Operand& right, Register overflow_dst,
Register scratch = at);
void SubuAndCheckForOverflow(Register dst,
Register left,
Register right,
Register overflow_dst,
Register scratch = at);
void SubuAndCheckForOverflow(Register dst, Register left,
const Operand& right, Register overflow_dst,
Register scratch = at);
void BranchOnOverflow(Label* label,
Register overflow_check,
BranchDelaySlot bd = PROTECT) {
Branch(label, lt, overflow_check, Operand(zero_reg), bd);
inline void AddBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) {
AddBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
}
void BranchOnNoOverflow(Label* label,
Register overflow_check,
BranchDelaySlot bd = PROTECT) {
Branch(label, ge, overflow_check, Operand(zero_reg), bd);
inline void AddBranchNoOvf(Register dst, Register left, const Operand& right,
Label* no_overflow_label, Register scratch = at) {
AddBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
}
void RetOnOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
Ret(lt, overflow_check, Operand(zero_reg), bd);
void AddBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void AddBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
inline void SubBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) {
SubBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
}
void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
Ret(ge, overflow_check, Operand(zero_reg), bd);
inline void SubBranchNoOvf(Register dst, Register left, const Operand& right,
Label* no_overflow_label, Register scratch = at) {
SubBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
}
void SubBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void SubBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
// -------------------------------------------------------------------------
// Runtime calls.
......@@ -1405,14 +1402,23 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
Addu(reg, reg, reg);
}
void SmiTag(Register dst, Register src) { Addu(dst, src, src); }
// Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
void SmiTagCheckOverflow(Register reg, Register overflow);
void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
void SmiTag(Register dst, Register src) {
Addu(dst, src, src);
void BranchOnOverflow(Label* label, Register overflow_check,
BranchDelaySlot bd = PROTECT) {
Branch(label, lt, overflow_check, Operand(zero_reg), bd);
}
void BranchOnNoOverflow(Label* label, Register overflow_check,
BranchDelaySlot bd = PROTECT) {
Branch(label, ge, overflow_check, Operand(zero_reg), bd);
}
// Try to convert int32 to smi. If the value is to large, preserve
// the original value and jump to not_a_smi. Destroys scratch and
// sets flags.
......
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