Reviewers: Jakob, danno, Paul Lind, kisg,
Description:
MIPS: Refactor Math.min/max to be a single HInstruction.
Port r12265 (7501dd73)
BUG=
TEST=
Please review this at https://chromiumcodereview.appspot.com/10854053/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/mips/lithium-codegen-mips.cc
M src/mips/lithium-mips.h
M src/mips/lithium-mips.cc
Index: src/mips/lithium-codegen-mips.cc
diff --git a/src/mips/lithium-codegen-mips.cc
b/src/mips/lithium-codegen-mips.cc
index
ac0395d9856153357e4328bbe5728bca78f4e4b6..82f337cfc8a43e7a8d4a450aa3524574bffabd15
100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1360,6 +1360,71 @@ void LCodeGen::DoAddI(LAddI* instr) {
}
+void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
+ LOperand* left = instr->InputAt(0);
+ LOperand* right = instr->InputAt(1);
+ HMathMinMax::Operation operation = instr->hydrogen()->operation();
+ Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
+ if (instr->hydrogen()->representation().IsInteger32()) {
+ Register left_reg = ToRegister(left);
+ Operand right_op = (right->IsRegister() || right->IsConstantOperand())
+ ? ToOperand(right)
+ : Operand(EmitLoadRegister(right, at));
+ Register result_reg = ToRegister(instr->result());
+ Label return_right, done;
+ if (!result_reg.is(left_reg)) {
+ __ Branch(&return_right, NegateCondition(condition), left_reg,
right_op);
+ __ mov(result_reg, left_reg);
+ __ Branch(&done);
+ }
+ __ Branch(&done, condition, left_reg, right_op);
+ __ bind(&return_right);
+ __ Addu(result_reg, zero_reg, right_op);
+ __ bind(&done);
+ } else {
+ ASSERT(instr->hydrogen()->representation().IsDouble());
+ FPURegister left_reg = ToDoubleRegister(left);
+ FPURegister right_reg = ToDoubleRegister(right);
+ FPURegister result_reg = ToDoubleRegister(instr->result());
+ Label check_nan_left, check_zero, return_left, return_right, done;
+ __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg);
+ __ BranchF(&return_left, NULL, condition, left_reg, right_reg);
+ __ Branch(&return_right);
+
+ __ bind(&check_zero);
+ // left == right != 0.
+ __ BranchF(&return_left, NULL, ne, left_reg, kDoubleRegZero);
+ // At this point, both left and right are either 0 or -0.
+ if (operation == HMathMinMax::kMathMin) {
+ // We could use a single 'vorr' instruction here if we had NEON
support.
+ __ neg_d(left_reg, left_reg);
+ __ sub_d(result_reg, left_reg, right_reg);
+ __ neg_d(result_reg, result_reg);
+ } else {
+ // Since we operate on +0 and/or -0, vadd and vand have the same
effect;
+ // the decision for vadd is easy because vand is a NEON instruction.
+ __ add_d(result_reg, left_reg, right_reg);
+ }
+ __ Branch(&done);
+
+ __ bind(&check_nan_left);
+ // left == NaN.
+ __ BranchF(NULL, &return_left, eq, left_reg, left_reg);
+ __ bind(&return_right);
+ if (!right_reg.is(result_reg)) {
+ __ mov_d(result_reg, right_reg);
+ }
+ __ Branch(&done);
+
+ __ bind(&return_left);
+ if (!left_reg.is(result_reg)) {
+ __ mov_d(result_reg, left_reg);
+ }
+ __ bind(&done);
+ }
+}
+
+
void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
DoubleRegister left = ToDoubleRegister(instr->InputAt(0));
DoubleRegister right = ToDoubleRegister(instr->InputAt(1));
Index: src/mips/lithium-mips.cc
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index
3513d20bd1db65d47c5b78edf6117cbb48cd7ae3..6cbb2a123747ad5c0e6016c13ca1243068476f31
100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1296,6 +1296,25 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
}
+LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
+ LOperand* left = NULL;
+ LOperand* right = NULL;
+ if (instr->representation().IsInteger32()) {
+ ASSERT(instr->left()->representation().IsInteger32());
+ ASSERT(instr->right()->representation().IsInteger32());
+ left = UseRegisterAtStart(instr->LeastConstantOperand());
+ right = UseOrConstantAtStart(instr->MostConstantOperand());
+ } else {
+ ASSERT(instr->representation().IsDouble());
+ ASSERT(instr->left()->representation().IsDouble());
+ ASSERT(instr->right()->representation().IsDouble());
+ left = UseRegisterAtStart(instr->left());
+ right = UseRegisterAtStart(instr->right());
+ }
+ return DefineAsRegister(new(zone()) LMathMinMax(left, right));
+}
+
+
LInstruction* LChunkBuilder::DoPower(HPower* instr) {
ASSERT(instr->representation().IsDouble());
// We call a C function for double power. It can't trigger a GC.
Index: src/mips/lithium-mips.h
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index
5d5de5e9d16b77810a0c74f3dd0af93e05b6b402..5aba86dd1d9ef9156202e35665edbd69455b0ac7
100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -115,7 +115,6 @@ class LCodeGen;
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
- V(StringCompareAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
@@ -132,6 +131,7 @@ class LCodeGen;
V(LoadNamedField) \
V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
+ V(MathMinMax) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@@ -162,6 +162,7 @@ class LCodeGen;
V(StringAdd) \
V(StringCharCodeAt) \
V(StringCharFromCode) \
+ V(StringCompareAndBranch) \
V(StringLength) \
V(SubI) \
V(TaggedToI) \
@@ -1049,6 +1050,18 @@ class LAddI: public LTemplateInstruction<1, 2, 0> {
};
+class LMathMinMax: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LMathMinMax(LOperand* left, LOperand* right) {
+ inputs_[0] = left;
+ inputs_[1] = right;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "min-max")
+ DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
+};
+
+
class LPower: public LTemplateInstruction<1, 2, 0> {
public:
LPower(LOperand* left, LOperand* right) {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev