Commit 15d56ffe authored by plind44@gmail.com's avatar plind44@gmail.com

MIPS: Improve integer multiplication.

Port r16576 (8ce78a4)

TEST=test/mjsunit/lithium/MulI.js
BUG=
R=plind44@gmail.com

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

Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16997 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 112b59ef
......@@ -1403,11 +1403,11 @@ void LCodeGen::DoMulI(LMulI* instr) {
Register left = ToRegister(instr->left());
LOperand* right_op = instr->right();
bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
bool bailout_on_minus_zero =
instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
if (right_op->IsConstantOperand() && !can_overflow) {
if (right_op->IsConstantOperand()) {
int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
if (bailout_on_minus_zero && (constant < 0)) {
......@@ -1418,7 +1418,12 @@ void LCodeGen::DoMulI(LMulI* instr) {
switch (constant) {
case -1:
__ Subu(result, zero_reg, left);
if (overflow) {
__ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
} else {
__ Subu(result, zero_reg, left);
}
break;
case 0:
if (bailout_on_minus_zero) {
......@@ -1439,27 +1444,23 @@ void LCodeGen::DoMulI(LMulI* instr) {
int32_t mask = constant >> 31;
uint32_t constant_abs = (constant + mask) ^ mask;
if (IsPowerOf2(constant_abs) ||
IsPowerOf2(constant_abs - 1) ||
IsPowerOf2(constant_abs + 1)) {
if (IsPowerOf2(constant_abs)) {
int32_t shift = WhichPowerOf2(constant_abs);
__ sll(result, left, shift);
} else if (IsPowerOf2(constant_abs - 1)) {
int32_t shift = WhichPowerOf2(constant_abs - 1);
__ sll(scratch, left, shift);
__ Addu(result, scratch, left);
} else if (IsPowerOf2(constant_abs + 1)) {
int32_t shift = WhichPowerOf2(constant_abs + 1);
__ sll(scratch, left, shift);
__ Subu(result, scratch, left);
}
// Correct the sign of the result is the constant is negative.
if (constant < 0) {
__ Subu(result, zero_reg, result);
}
if (IsPowerOf2(constant_abs)) {
int32_t shift = WhichPowerOf2(constant_abs);
__ sll(result, left, shift);
// Correct the sign of the result if the constant is negative.
if (constant < 0) __ Subu(result, zero_reg, result);
} else if (IsPowerOf2(constant_abs - 1)) {
int32_t shift = WhichPowerOf2(constant_abs - 1);
__ sll(scratch, left, shift);
__ Addu(result, scratch, left);
// Correct the sign of the result if the constant is negative.
if (constant < 0) __ Subu(result, zero_reg, result);
} else if (IsPowerOf2(constant_abs + 1)) {
int32_t shift = WhichPowerOf2(constant_abs + 1);
__ sll(scratch, left, shift);
__ Subu(result, scratch, left);
// Correct the sign of the result if the constant is negative.
if (constant < 0) __ Subu(result, zero_reg, result);
} else {
// Generate standard code.
__ li(at, constant);
......@@ -1468,12 +1469,10 @@ void LCodeGen::DoMulI(LMulI* instr) {
}
} else {
Register right = EmitLoadRegister(right_op, scratch);
if (bailout_on_minus_zero) {
__ Or(ToRegister(instr->temp()), left, right);
}
ASSERT(right_op->IsRegister());
Register right = ToRegister(right_op);
if (can_overflow) {
if (overflow) {
// hi:lo = left * right.
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiUntag(result, left);
......@@ -1497,12 +1496,13 @@ void LCodeGen::DoMulI(LMulI* instr) {
}
if (bailout_on_minus_zero) {
// Bail out if the result is supposed to be negative zero.
Label done;
__ Branch(&done, ne, result, Operand(zero_reg));
DeoptimizeIf(lt,
__ Xor(at, left, right);
__ Branch(&done, ge, at, Operand(zero_reg));
// Bail out if the result is minus zero.
DeoptimizeIf(eq,
instr->environment(),
ToRegister(instr->temp()),
result,
Operand(zero_reg));
__ bind(&done);
}
......
......@@ -1469,20 +1469,39 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
if (instr->representation().IsSmiOrInteger32()) {
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* left;
LOperand* right = UseOrConstant(instr->BetterRightOperand());
LOperand* temp = NULL;
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
(instr->CheckFlag(HValue::kCanOverflow) ||
!right->IsConstantOperand())) {
left = UseRegister(instr->BetterLeftOperand());
temp = TempRegister();
HValue* left = instr->BetterLeftOperand();
HValue* right = instr->BetterRightOperand();
LOperand* left_op;
LOperand* right_op;
bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
if (right->IsConstant()) {
HConstant* constant = HConstant::cast(right);
int32_t constant_value = constant->Integer32Value();
// Constants -1, 0 and 1 can be optimized if the result can overflow.
// For other constants, it can be optimized only without overflow.
if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
left_op = UseRegisterAtStart(left);
right_op = UseConstant(right);
} else {
if (bailout_on_minus_zero) {
left_op = UseRegister(left);
} else {
left_op = UseRegisterAtStart(left);
}
right_op = UseRegister(right);
}
} else {
left = UseRegisterAtStart(instr->BetterLeftOperand());
if (bailout_on_minus_zero) {
left_op = UseRegister(left);
} else {
left_op = UseRegisterAtStart(left);
}
right_op = UseRegister(right);
}
LMulI* mul = new(zone()) LMulI(left, right, temp);
if (instr->CheckFlag(HValue::kCanOverflow) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
LMulI* mul = new(zone()) LMulI(left_op, right_op);
if (can_overflow || bailout_on_minus_zero) {
AssignEnvironment(mul);
}
return DefineAsRegister(mul);
......
......@@ -688,17 +688,15 @@ class LMathFloorOfDiv V8_FINAL : public LTemplateInstruction<1, 2, 1> {
};
class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
public:
LMulI(LOperand* left, LOperand* right, LOperand* temp) {
LMulI(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
temps_[0] = temp;
}
LOperand* left() { return inputs_[0]; }
LOperand* right() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
DECLARE_HYDROGEN_ACCESSOR(Mul)
......
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