From 37d11fb0f001352ae04fd9db4884a2414b91a5e2 Mon Sep 17 00:00:00 2001 From: "mvstanton@chromium.org" Date: Mon, 22 Apr 2013 07:47:25 +0000 Subject: [PATCH] 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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14364 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 11 +++- src/arm/lithium-codegen-arm.cc | 22 ++++--- src/ia32/lithium-codegen-ia32.cc | 97 ++++++++++++++++++----------- src/ia32/lithium-ia32.cc | 46 ++++++++++---- src/x64/lithium-codegen-x64.cc | 103 +++++++++++++++++++------------ src/x64/lithium-x64.cc | 32 ++++++++-- 6 files changed, 211 insertions(+), 100 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 1314e782e5..618ac10245 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -2460,8 +2460,15 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { 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)); } diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index f47e7e8e0e..5c15d49787 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -3277,14 +3277,22 @@ void LCodeGen::DoLoadExternalArrayPointer( 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)); + } } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 221882ca04..de62e1fd3b 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -3196,13 +3196,21 @@ void LCodeGen::DoLoadExternalArrayPointer( 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::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { 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 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 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 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::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { 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 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { 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 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 = diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 523673ae2f..4daf3091bb 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -2297,19 +2297,21 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { 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 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { : 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::DoArgumentsObject(HArgumentsObject* instr) { 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)); } diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 21b0fcdd3b..fa1227085d 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2899,16 +2899,26 @@ void LCodeGen::DoLoadExternalArrayPointer( 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::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { 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 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 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 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::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { 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 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { 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 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 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { // 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); } } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index d3651746d2..e78cee4837 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -2139,7 +2139,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { 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 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { : 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::DoArgumentsObject(HArgumentsObject* instr) { 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)); }