From a290160f74ee53c0ffb51c7b3ac916d239c9556a Mon Sep 17 00:00:00 2001 From: Lena Djokic Date: Thu, 21 Sep 2017 13:50:52 +0200 Subject: MIPS32R2: Share address computation For array accesses the element address has the following structure: Address = CONST_OFFSET + base_addr + index << ELEM_SHIFT The address part (index << ELEM_SHIFT) can be shared across array accesses with the same data type and index. For example, in the following loop 5 accesses can share address computation: void foo(int[] a, int[] b, int[] c) { for (i...) { a[i] = a[i] + 5; b[i] = b[i] + c[i]; } } Test: test-art-host, test-art-target Change-Id: Id09fa782934aad4ee47669275e7e1a4d7d23b0fa --- compiler/optimizing/code_generator_mips.cc | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'compiler/optimizing/code_generator_mips.cc') diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 70c8a5b523..3c592e7e37 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -2665,6 +2665,9 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { __ ShiftAndAdd(TMP, index_reg, obj, TIMES_2, TMP); __ LoadFromOffset(kLoadUnsignedHalfword, out, TMP, data_offset); __ Bind(&done); + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(TMP, index_reg, obj); + __ LoadFromOffset(kLoadUnsignedHalfword, out, TMP, data_offset, null_checker); } else { __ ShiftAndAdd(TMP, index_reg, obj, TIMES_2, TMP); __ LoadFromOffset(kLoadUnsignedHalfword, out, TMP, data_offset, null_checker); @@ -2679,6 +2682,9 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset; __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset, null_checker); + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(TMP, index.AsRegister(), obj); + __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset, null_checker); } else { __ ShiftAndAdd(TMP, index.AsRegister(), obj, TIMES_2, TMP); __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset, null_checker); @@ -2693,6 +2699,9 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; __ LoadFromOffset(kLoadWord, out, obj, offset, null_checker); + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(TMP, index.AsRegister(), obj); + __ LoadFromOffset(kLoadWord, out, TMP, data_offset, null_checker); } else { __ ShiftAndAdd(TMP, index.AsRegister(), obj, TIMES_4, TMP); __ LoadFromOffset(kLoadWord, out, TMP, data_offset, null_checker); @@ -2766,6 +2775,9 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset; __ LoadFromOffset(kLoadDoubleword, out, obj, offset, null_checker); + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(TMP, index.AsRegister(), obj); + __ LoadFromOffset(kLoadDoubleword, out, TMP, data_offset, null_checker); } else { __ ShiftAndAdd(TMP, index.AsRegister(), obj, TIMES_8, TMP); __ LoadFromOffset(kLoadDoubleword, out, TMP, data_offset, null_checker); @@ -2779,6 +2791,9 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; __ LoadSFromOffset(out, obj, offset, null_checker); + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(TMP, index.AsRegister(), obj); + __ LoadSFromOffset(out, TMP, data_offset, null_checker); } else { __ ShiftAndAdd(TMP, index.AsRegister(), obj, TIMES_4, TMP); __ LoadSFromOffset(out, TMP, data_offset, null_checker); @@ -2792,6 +2807,9 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset; __ LoadDFromOffset(out, obj, offset, null_checker); + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(TMP, index.AsRegister(), obj); + __ LoadDFromOffset(out, TMP, data_offset, null_checker); } else { __ ShiftAndAdd(TMP, index.AsRegister(), obj, TIMES_8, TMP); __ LoadDFromOffset(out, TMP, data_offset, null_checker); @@ -2906,6 +2924,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2; + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(base_reg, index.AsRegister(), obj); } else { __ ShiftAndAdd(base_reg, index.AsRegister(), obj, TIMES_2, base_reg); } @@ -2923,6 +2943,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4; + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(base_reg, index.AsRegister(), obj); } else { __ ShiftAndAdd(base_reg, index.AsRegister(), obj, TIMES_4, base_reg); } @@ -2972,6 +2994,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4; + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(base_reg, index.AsRegister(), obj); } else { __ ShiftAndAdd(base_reg, index.AsRegister(), obj, TIMES_4, base_reg); } @@ -3055,6 +3079,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8; + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(base_reg, index.AsRegister(), obj); } else { __ ShiftAndAdd(base_reg, index.AsRegister(), obj, TIMES_8, base_reg); } @@ -3072,6 +3098,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4; + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(base_reg, index.AsRegister(), obj); } else { __ ShiftAndAdd(base_reg, index.AsRegister(), obj, TIMES_4, base_reg); } @@ -3089,6 +3117,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8; + } else if (instruction->InputAt(1)->IsIntermediateArrayAddressIndex()) { + __ Addu(base_reg, index.AsRegister(), obj); } else { __ ShiftAndAdd(base_reg, index.AsRegister(), obj, TIMES_8, base_reg); } @@ -3108,6 +3138,26 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { } } +void LocationsBuilderMIPS::VisitIntermediateArrayAddressIndex( + HIntermediateArrayAddressIndex* instruction) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); + + HIntConstant* shift = instruction->GetShift()->AsIntConstant(); + + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetInAt(1, Location::ConstantLocation(shift)); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); +} + +void InstructionCodeGeneratorMIPS::VisitIntermediateArrayAddressIndex( + HIntermediateArrayAddressIndex* instruction) { + LocationSummary* locations = instruction->GetLocations(); + Register index_reg = locations->InAt(0).AsRegister(); + uint32_t shift = instruction->GetShift()->AsIntConstant()->GetValue(); + __ Sll(locations->Out().AsRegister(), index_reg, shift); +} + void LocationsBuilderMIPS::VisitBoundsCheck(HBoundsCheck* instruction) { RegisterSet caller_saves = RegisterSet::Empty(); InvokeRuntimeCallingConvention calling_convention; -- cgit v1.2.3