Revision: 14364
Author:   [email protected]
Date:     Mon Apr 22 00:47:25 2013
Log: Improvements in lithium code generation. Recognizing if some operands are constants, we can often save on registers and instructions.

BUG=

Review URL: https://codereview.chromium.org/14022011
http://code.google.com/p/v8/source/detail?r=14364

Modified:
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Thu Apr 18 08:44:38 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Mon Apr 22 00:47:25 2013
@@ -2460,8 +2460,15 @@
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
   info()->MarkAsRequiresFrame();
   LOperand* args = UseRegister(instr->arguments());
-  LOperand* length = UseTempRegister(instr->length());
-  LOperand* index = UseRegister(instr->index());
+  LOperand* length;
+  LOperand* index;
+  if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
+    length = UseRegisterOrConstant(instr->length());
+    index = UseOrConstant(instr->index());
+  } else {
+    length = UseTempRegister(instr->length());
+    index = Use(instr->index());
+  }
return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
 }

=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Apr 19 09:01:57 2013 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Apr 22 00:47:25 2013
@@ -3277,14 +3277,22 @@

 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
   Register arguments = ToRegister(instr->arguments());
-  Register length = ToRegister(instr->length());
-  Register index = ToRegister(instr->index());
   Register result = ToRegister(instr->result());
-  // There are two words between the frame pointer and the last argument.
-  // Subtracting from length accounts for one of them add one more.
-  __ sub(length, length, index);
-  __ add(length, length, Operand(1));
-  __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
+  if (instr->length()->IsConstantOperand() &&
+      instr->index()->IsConstantOperand()) {
+    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
+    int index = (const_length - const_index) + 1;
+    __ ldr(result, MemOperand(arguments, index * kPointerSize));
+  } else {
+    Register length = ToRegister(instr->length());
+    Register index = ToRegister(instr->index());
+    // There are two words between the frame pointer and the last argument.
+    // Subtracting from length accounts for one of them add one more.
+    __ sub(length, length, index);
+    __ add(length, length, Operand(1));
+    __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
+  }
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Apr 19 05:02:12 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon Apr 22 00:47:25 2013
@@ -3196,13 +3196,21 @@

 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
   Register arguments = ToRegister(instr->arguments());
-  Register length = ToRegister(instr->length());
-  Operand index = ToOperand(instr->index());
   Register result = ToRegister(instr->result());
-  // There are two words between the frame pointer and the last argument.
-  // Subtracting from length accounts for one of them add one more.
-  __ sub(length, index);
-  __ mov(result, Operand(arguments, length, times_4, kPointerSize));
+  if (instr->length()->IsConstantOperand() &&
+      instr->index()->IsConstantOperand()) {
+    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
+    int index = (const_length - const_index) + 1;
+    __ mov(result, Operand(arguments, index * kPointerSize));
+  } else {
+    Register length = ToRegister(instr->length());
+    Operand index = ToOperand(instr->index());
+    // There are two words between the frame pointer and the last argument.
+    // Subtracting from length accounts for one of them add one more.
+    __ sub(length, index);
+    __ mov(result, Operand(arguments, length, times_4, kPointerSize));
+  }
 }


@@ -4220,7 +4228,6 @@

 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   Register object = ToRegister(instr->object());
-  Register value = ToRegister(instr->value());
   int offset = instr->offset();

   if (!instr->transition().is_null()) {
@@ -4246,34 +4253,42 @@
   HType type = instr->hydrogen()->value()->type();
   SmiCheck check_needed =
       type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
-  if (instr->is_in_object()) {
-    __ mov(FieldOperand(object, offset), value);
-    if (instr->hydrogen()->NeedsWriteBarrier()) {
-      Register temp = ToRegister(instr->temp());
-      // Update the write barrier for the object for in-object properties.
-      __ RecordWriteField(object,
-                          offset,
-                          value,
-                          temp,
-                          GetSaveFPRegsMode(),
-                          EMIT_REMEMBERED_SET,
-                          check_needed);
+
+  Register write_register = object;
+  if (!instr->is_in_object()) {
+    write_register = ToRegister(instr->temp());
+    __ mov(write_register,
+           FieldOperand(object, JSObject::kPropertiesOffset));
+  }
+
+  if (instr->value()->IsConstantOperand()) {
+ LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
+    if (IsInteger32(operand_value)) {
+      int const_value = ToInteger32(operand_value);
+      __ mov(FieldOperand(write_register, offset), Immediate(const_value));
+    } else {
+      if (operand_value->IsRegister()) {
+ __ mov(FieldOperand(write_register, offset), ToRegister(operand_value));
+      } else {
+        Handle<Object> handle_value = ToHandle(operand_value);
+        __ mov(FieldOperand(write_register, offset), handle_value);
+      }
     }
   } else {
-    Register temp = ToRegister(instr->temp());
-    __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset));
-    __ mov(FieldOperand(temp, offset), value);
-    if (instr->hydrogen()->NeedsWriteBarrier()) {
-      // Update the write barrier for the properties array.
-      // object is used as a scratch register.
-      __ RecordWriteField(temp,
-                          offset,
-                          value,
-                          object,
-                          GetSaveFPRegsMode(),
-                          EMIT_REMEMBERED_SET,
-                          check_needed);
-    }
+ __ mov(FieldOperand(write_register, offset), ToRegister(instr->value()));
+  }
+
+  if (instr->hydrogen()->NeedsWriteBarrier()) {
+    Register value = ToRegister(instr->value());
+ Register temp = instr->is_in_object() ? ToRegister(instr->temp()) : object;
+    // Update the write barrier for the object for in-object properties.
+    __ RecordWriteField(write_register,
+                        offset,
+                        value,
+                        temp,
+                        GetSaveFPRegsMode(),
+                        EMIT_REMEMBERED_SET,
+                        check_needed);
   }
 }

@@ -4451,7 +4466,6 @@


 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
-  Register value = ToRegister(instr->value());
   Register elements = ToRegister(instr->elements());
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;

@@ -4462,9 +4476,22 @@
       FAST_ELEMENTS,
       FixedArray::kHeaderSize - kHeapObjectTag,
       instr->additional_index());
-  __ mov(operand, value);
+  if (instr->value()->IsRegister()) {
+    __ mov(operand, ToRegister(instr->value()));
+  } else {
+ LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
+    if (IsInteger32(operand_value)) {
+      Smi* smi_value = Smi::FromInt(ToInteger32(operand_value));
+      __ mov(operand, Immediate(smi_value));
+    } else {
+      Handle<Object> handle_value = ToHandle(operand_value);
+      __ mov(operand, handle_value);
+    }
+  }

   if (instr->hydrogen()->NeedsWriteBarrier()) {
+    ASSERT(instr->value()->IsRegister());
+    Register value = ToRegister(instr->value());
     ASSERT(!instr->key()->IsConstantOperand());
     HType type = instr->hydrogen()->value()->type();
     SmiCheck check_needed =
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Thu Apr 18 08:44:38 2013 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Mon Apr 22 00:47:25 2013
@@ -2297,19 +2297,21 @@
         val = UseX87TopOfStack(instr->value());
       }
       LOperand* key = UseRegisterOrConstantAtStart(instr->key());
-
       return new(zone()) LStoreKeyed(object, key, val);
     } else {
       ASSERT(instr->value()->representation().IsTagged());
       bool needs_write_barrier = instr->NeedsWriteBarrier();

       LOperand* obj = UseRegister(instr->elements());
-      LOperand* val = needs_write_barrier
-          ? UseTempRegister(instr->value())
-          : UseRegisterAtStart(instr->value());
-      LOperand* key = needs_write_barrier
-          ? UseTempRegister(instr->key())
-          : UseRegisterOrConstantAtStart(instr->key());
+      LOperand* val;
+      LOperand* key;
+      if (needs_write_barrier) {
+        val = UseTempRegister(instr->value());
+        key = UseTempRegister(instr->key());
+      } else {
+        val = UseRegisterOrConstantAtStart(instr->value());
+        key = UseRegisterOrConstantAtStart(instr->key());
+      }
       return new(zone()) LStoreKeyed(obj, key, val);
     }
   }
@@ -2409,9 +2411,22 @@
         : UseRegisterAtStart(instr->object());
   }

-  LOperand* val = needs_write_barrier
-      ? UseTempRegister(instr->value())
-      : UseRegister(instr->value());
+  bool register_or_constant = false;
+  if (instr->value()->IsConstant()) {
+    HConstant* constant_value = HConstant::cast(instr->value());
+    register_or_constant = constant_value->HasInteger32Value()
+        || constant_value->HasDoubleValue()
+        || constant_value->ImmortalImmovable();
+  }
+
+  LOperand* val;
+  if (needs_write_barrier) {
+    val = UseTempRegister(instr->value());
+  } else if (register_or_constant) {
+    val = UseRegisterOrConstant(instr->value());
+  } else {
+    val = UseRegister(instr->value());
+  }

   // We only need a scratch register if we have a write barrier or we
   // have a store into the properties array (not in-object-property).
@@ -2579,8 +2594,15 @@
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
   info()->MarkAsRequiresFrame();
   LOperand* args = UseRegister(instr->arguments());
-  LOperand* length = UseTempRegister(instr->length());
-  LOperand* index = Use(instr->index());
+  LOperand* length;
+  LOperand* index;
+  if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
+    length = UseRegisterOrConstant(instr->length());
+    index = UseOrConstant(instr->index());
+  } else {
+    length = UseTempRegister(instr->length());
+    index = Use(instr->index());
+  }
return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
 }

=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Apr 19 05:02:12 2013 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon Apr 22 00:47:25 2013
@@ -2899,16 +2899,26 @@

 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
   Register arguments = ToRegister(instr->arguments());
-  Register length = ToRegister(instr->length());
   Register result = ToRegister(instr->result());
-  // There are two words between the frame pointer and the last argument.
-  // Subtracting from length accounts for one of them add one more.
-  if (instr->index()->IsRegister()) {
-    __ subl(length, ToRegister(instr->index()));
+
+  if (instr->length()->IsConstantOperand() &&
+      instr->index()->IsConstantOperand()) {
+    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
+    int index = (const_length - const_index) + 1;
+    __ movq(result, Operand(arguments, index * kPointerSize));
   } else {
-    __ subl(length, ToOperand(instr->index()));
+    Register length = ToRegister(instr->length());
+    // There are two words between the frame pointer and the last argument.
+    // Subtracting from length accounts for one of them add one more.
+    if (instr->index()->IsRegister()) {
+      __ subl(length, ToRegister(instr->index()));
+    } else {
+      __ subl(length, ToOperand(instr->index()));
+    }
+    __ movq(result,
+            Operand(arguments, length, times_pointer_size, kPointerSize));
   }
- __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize));
 }


@@ -3916,7 +3926,6 @@

 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   Register object = ToRegister(instr->object());
-  Register value = ToRegister(instr->value());
   int offset = instr->offset();

   if (!instr->transition().is_null()) {
@@ -3942,34 +3951,42 @@
   HType type = instr->hydrogen()->value()->type();
   SmiCheck check_needed =
       type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
-  if (instr->is_in_object()) {
-    __ movq(FieldOperand(object, offset), value);
-    if (instr->hydrogen()->NeedsWriteBarrier()) {
-      Register temp = ToRegister(instr->temp());
-      // Update the write barrier for the object for in-object properties.
-      __ RecordWriteField(object,
-                          offset,
-                          value,
-                          temp,
-                          kSaveFPRegs,
-                          EMIT_REMEMBERED_SET,
-                          check_needed);
+
+  Register write_register = object;
+  if (!instr->is_in_object()) {
+    write_register = ToRegister(instr->temp());
+ __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
+  }
+
+  if (instr->value()->IsConstantOperand()) {
+ LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
+    if (IsInteger32Constant(operand_value)) {
+      int const_value = ToInteger32(operand_value);
+ __ movq(FieldOperand(write_register, offset), Immediate(const_value));
+    } else {
+      if (operand_value->IsRegister()) {
+        __ movq(FieldOperand(write_register, offset),
+                ToRegister(operand_value));
+      } else {
+        Handle<Object> handle_value = ToHandle(operand_value);
+        __ Move(FieldOperand(write_register, offset), handle_value);
+      }
     }
   } else {
-    Register temp = ToRegister(instr->temp());
-    __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset));
-    __ movq(FieldOperand(temp, offset), value);
-    if (instr->hydrogen()->NeedsWriteBarrier()) {
-      // Update the write barrier for the properties array.
-      // object is used as a scratch register.
-      __ RecordWriteField(temp,
-                          offset,
-                          value,
-                          object,
-                          kSaveFPRegs,
-                          EMIT_REMEMBERED_SET,
-                          check_needed);
-    }
+ __ movq(FieldOperand(write_register, offset), ToRegister(instr->value()));
+  }
+
+  if (instr->hydrogen()->NeedsWriteBarrier()) {
+    Register value = ToRegister(instr->value());
+ Register temp = instr->is_in_object() ? ToRegister(instr->temp()) : object;
+    // Update the write barrier for the object for in-object properties.
+    __ RecordWriteField(write_register,
+                        offset,
+                        value,
+                        temp,
+                        kSaveFPRegs,
+                        EMIT_REMEMBERED_SET,
+                        check_needed);
   }
 }

@@ -4135,7 +4152,6 @@


 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
-  Register value = ToRegister(instr->value());
   Register elements = ToRegister(instr->elements());
   LOperand* key = instr->key();
   if (!key->IsConstantOperand()) {
@@ -4160,8 +4176,22 @@
                             FAST_ELEMENTS,
                             FixedArray::kHeaderSize - kHeapObjectTag,
                             instr->additional_index());
+  if (instr->value()->IsRegister()) {
+    __ movq(operand, ToRegister(instr->value()));
+  } else {
+ LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
+    if (IsInteger32Constant(operand_value)) {
+      Smi* smi_value = Smi::FromInt(ToInteger32(operand_value));
+      __ Move(operand, smi_value);
+    } else {
+      Handle<Object> handle_value = ToHandle(operand_value);
+      __ Move(operand, handle_value);
+    }
+  }

   if (instr->hydrogen()->NeedsWriteBarrier()) {
+    ASSERT(instr->value()->IsRegister());
+    Register value = ToRegister(instr->value());
     ASSERT(!instr->key()->IsConstantOperand());
     HType type = instr->hydrogen()->value()->type();
     SmiCheck check_needed =
@@ -4169,15 +4199,12 @@
     // Compute address of modified element and store it into key register.
     Register key_reg(ToRegister(key));
     __ lea(key_reg, operand);
-    __ movq(Operand(key_reg, 0), value);
     __ RecordWrite(elements,
                    key_reg,
                    value,
                    kSaveFPRegs,
                    EMIT_REMEMBERED_SET,
                    check_needed);
-  } else {
-    __ movq(operand, value);
   }
 }

=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc      Thu Apr 18 08:44:38 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Mon Apr 22 00:47:25 2013
@@ -2139,7 +2139,7 @@
       ASSERT(instr->value()->representation().IsTagged());
       object = UseTempRegister(instr->elements());
       val = needs_write_barrier ? UseTempRegister(instr->value())
-          : UseRegisterAtStart(instr->value());
+          : UseRegisterOrConstantAtStart(instr->value());
       key = (clobbers_key || needs_write_barrier)
           ? UseTempRegister(instr->key())
           : UseRegisterOrConstantAtStart(instr->key());
@@ -2236,9 +2236,22 @@
         : UseRegisterAtStart(instr->object());
   }

-  LOperand* val = needs_write_barrier
-      ? UseTempRegister(instr->value())
-      : UseRegister(instr->value());
+  bool register_or_constant = false;
+  if (instr->value()->IsConstant()) {
+    HConstant* constant_value = HConstant::cast(instr->value());
+    register_or_constant = constant_value->HasInteger32Value()
+        || constant_value->HasDoubleValue()
+        || constant_value->ImmortalImmovable();
+  }
+
+  LOperand* val;
+  if (needs_write_barrier) {
+    val = UseTempRegister(instr->value());
+  } else if (register_or_constant) {
+    val = UseRegisterOrConstant(instr->value());
+  } else {
+    val = UseRegister(instr->value());
+  }

   // We only need a scratch register if we have a write barrier or we
   // have a store into the properties array (not in-object-property).
@@ -2382,8 +2395,15 @@
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
   info()->MarkAsRequiresFrame();
   LOperand* args = UseRegister(instr->arguments());
-  LOperand* length = UseTempRegister(instr->length());
-  LOperand* index = Use(instr->index());
+  LOperand* length;
+  LOperand* index;
+  if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
+    length = UseRegisterOrConstant(instr->length());
+    index = UseOrConstant(instr->index());
+  } else {
+    length = UseTempRegister(instr->length());
+    index = Use(instr->index());
+  }
return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
 }

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to