Revision: 7288
Author: [email protected]
Date: Mon Mar 21 07:31:15 2011
Log: ARM: Add optimization for constant RHS in DoMulI.
Patch by ARM Ltd.
Review URL: http://codereview.chromium.org/6708025
http://code.google.com/p/v8/source/detail?r=7288
Modified:
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/utils.h
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Mar 21
05:25:31 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Mar 21
07:31:15 2011
@@ -1013,40 +1013,123 @@
void LCodeGen::DoMulI(LMulI* instr) {
+ LOperand* left_op = instr->InputAt(0);
+ LOperand* right_op = instr->InputAt(1);
+
Register scratch = scratch0();
- Register left = ToRegister(instr->InputAt(0));
- Register right = EmitLoadRegister(instr->InputAt(1), scratch);
-
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
- !instr->InputAt(1)->IsConstantOperand()) {
- __ orr(ToRegister(instr->TempAt(0)), left, right);
- }
-
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
- // scratch:left = left * right.
- __ smull(left, scratch, left, right);
- __ mov(ip, Operand(left, ASR, 31));
- __ cmp(ip, Operand(scratch));
- DeoptimizeIf(ne, instr->environment());
- } else {
- __ mul(left, left, right);
- }
-
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- // Bail out if the result is supposed to be negative zero.
- Label done;
- __ tst(left, Operand(left));
- __ b(ne, &done);
- if (instr->InputAt(1)->IsConstantOperand()) {
- if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) {
- DeoptimizeIf(al, instr->environment());
- }
+ Register left = ToRegister(left_op);
+
+ ASSERT(left_op->Equals(instr->result()));
+
+ bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+ bool bailout_on_minus_zero =
+ instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
+
+ if (right_op->IsConstantOperand()) {
+ // Use optimized code for specific constants.
+ int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
+ Condition overflow_deopt_cond = kNoCondition;
+ switch (constant) {
+ case -1:
+ overflow_deopt_cond = can_overflow ? vs : kNoCondition;
+ __ rsb(left,
+ left,
+ Operand(0),
+ can_overflow ? SetCC : LeaveCC);
+ break;
+ case 0:
+ if (bailout_on_minus_zero) {
+ // If left is strictly negative and the constant is null, the
+ // result is -0. Deoptimize if required, otherwise return 0.
+ __ cmp(left, Operand(0));
+ DeoptimizeIf(mi, instr->environment());
+ }
+ __ mov(left, Operand(0));
+ break;
+ case 1:
+ // Do nothing.
+ break;
+ default:
+ // Multiplying by powers of two and powers of two plus or minus
+ // one can be done faster with shifted operands.
+ // For other constants we emit standard code.
+ int32_t mask = constant >> 31;
+ uint32_t constant_abs = (constant + mask) ^ mask;
+ if (IsPowerOf2(constant_abs)) {
+ if (!can_overflow) {
+ int32_t shift = WhichPowerOf2(constant_abs);
+ __ mov(left, Operand(left, LSL, shift));
+ if (constant < 0) __ rsb(left, left, Operand(0));
+ } else {
+ // scratch:left = left * constant.
+ __ mov(ip, Operand(constant));
+ __ smull(left, scratch, left, ip);
+ __ cmp(scratch, Operand(left, ASR, 31));
+ overflow_deopt_cond = ne;
+ }
+ } else if (IsPowerOf2(constant_abs - 1)) {
+ int32_t shift = WhichPowerOf2(constant_abs - 1);
+ __ add(left,
+ left,
+ Operand(left, LSL, shift),
+ can_overflow ? SetCC : LeaveCC);
+ overflow_deopt_cond = can_overflow ? vs : kNoCondition;
+ if (constant < 0) __ rsb(left, left, Operand(0));
+ } else if (IsPowerOf2(constant_abs + 1)) {
+ int32_t shift = WhichPowerOf2(constant_abs + 1);
+ __ rsb(left,
+ left,
+ Operand(left, LSL, shift),
+ can_overflow ? SetCC : LeaveCC);
+ overflow_deopt_cond = can_overflow ? vs : kNoCondition;
+ if (constant < 0) __ rsb(left, left, Operand(0));
+ } else {
+ if (!can_overflow) {
+ __ mov(ip, Operand(constant));
+ __ mul(left, left, ip);
+ } else {
+ // scratch:left = left * constant.
+ __ mov(ip, Operand(constant));
+ __ smull(left, scratch, left, ip);
+ __ cmp(scratch, Operand(left, ASR, 31));
+ overflow_deopt_cond = ne;
+ }
+ }
+ break;
+ }
+
+ if (can_overflow && (constant != 0) && (constant != 1)) {
+ ASSERT(overflow_deopt_cond != kNoCondition);
+ DeoptimizeIf(overflow_deopt_cond, instr->environment());
+ }
+ if (bailout_on_minus_zero && (constant < 0)) {
+ // The case of a null constant was handled separately.
+ // If constant is negative and left is null, the result should be -0.
+ __ cmp(left, Operand(0));
+ DeoptimizeIf(eq, instr->environment());
+ }
+ } else {
+ Register right = EmitLoadRegister(right_op, scratch);
+ if (bailout_on_minus_zero) {
+ __ orr(ToRegister(instr->TempAt(0)), left, right);
+ }
+ if (can_overflow) {
+ // scratch:left = left * right.
+ __ smull(left, scratch, left, right);
+ __ cmp(scratch, Operand(left, ASR, 31));
+ DeoptimizeIf(ne, instr->environment());
} else {
- // Test the non-zero operand for negative sign.
+ __ mul(left, left, right);
+ }
+ if (bailout_on_minus_zero) {
+ // Bail out if the result is supposed to be negative zero.
+ Label done;
+ __ cmp(left, Operand(0));
+ __ b(ne, &done);
__ cmp(ToRegister(instr->TempAt(0)), Operand(0));
DeoptimizeIf(mi, instr->environment());
- }
- __ bind(&done);
+ __ bind(&done);
+ }
}
}
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Mar 18
13:35:07 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Mar 21
07:31:15 2011
@@ -294,7 +294,8 @@
!src2.must_use_constant_pool() &&
Isolate::Current()->cpu_features()->IsSupported(ARMv7) &&
IsPowerOf2(src2.immediate() + 1)) {
- ubfx(dst, src1, 0, WhichPowerOf2(src2.immediate() + 1), cond);
+ ubfx(dst, src1, 0,
+ WhichPowerOf2(static_cast<uint32_t>(src2.immediate()) + 1), cond);
} else {
and_(dst, src1, src2, LeaveCC, cond);
=======================================
--- /branches/bleeding_edge/src/utils.h Mon Mar 21 02:59:29 2011
+++ /branches/bleeding_edge/src/utils.h Mon Mar 21 07:31:15 2011
@@ -52,11 +52,9 @@
// X must be a power of 2. Returns the number of trailing zeros.
-template <typename T>
-static inline int WhichPowerOf2(T x) {
+static inline int WhichPowerOf2(uint32_t x) {
ASSERT(IsPowerOf2(x));
ASSERT(x != 0);
- if (x < 0) return 31;
int bits = 0;
#ifdef DEBUG
int original_x = x;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev