diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc index 3271447e7b46..db87390ea66a 100644 --- a/runtime/vm/compiler/assembler/assembler_arm.cc +++ b/runtime/vm/compiler/assembler/assembler_arm.cc @@ -3539,9 +3539,8 @@ void Assembler::LoadAllocationTracingStateAddress(Register dest, Register cid) { ldr(dest, Address(dest, target::ClassTable::allocation_tracing_state_table_offset())); - AddScaled(cid, cid, TIMES_1, + AddScaled(dest, dest, cid, TIMES_1, target::ClassTable::AllocationTracingStateSlotOffsetFor(0)); - AddRegisters(dest, cid); } void Assembler::LoadAllocationTracingStateAddress(Register dest, intptr_t cid) { diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h index 4ea9f488c28f..d83733ee6a63 100644 --- a/runtime/vm/compiler/assembler/assembler_arm.h +++ b/runtime/vm/compiler/assembler/assembler_arm.h @@ -832,16 +832,21 @@ class Assembler : public AssemblerBase { void AddRegisters(Register dest, Register src) { add(dest, dest, Operand(src)); } - // [dest] = [src] << [scale] + [value]. void AddScaled(Register dest, - Register src, + Register base, + Register index, ScaleFactor scale, - int32_t value) { - if (scale == 0) { - AddImmediate(dest, src, value); + int32_t disp) override { + if (base == kNoRegister) { + if (scale == TIMES_1) { + AddImmediate(dest, index, disp); + } else { + Lsl(dest, index, Operand(scale)); + AddImmediate(dest, disp); + } } else { - Lsl(dest, src, Operand(scale)); - AddImmediate(dest, dest, value); + add(dest, base, compiler::Operand(index, LSL, scale)); + AddImmediate(dest, disp); } } void SubImmediate(Register rd, diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h index c384e684e3c8..521a0841c441 100644 --- a/runtime/vm/compiler/assembler/assembler_arm64.h +++ b/runtime/vm/compiler/assembler/assembler_arm64.h @@ -1784,16 +1784,21 @@ class Assembler : public AssemblerBase { void AddRegisters(Register dest, Register src) { add(dest, dest, Operand(src)); } - // [dest] = [src] << [scale] + [value]. void AddScaled(Register dest, - Register src, + Register base, + Register index, ScaleFactor scale, - int32_t value) { - if (scale == 0) { - AddImmediate(dest, src, value); + int32_t disp) override { + if (base == kNoRegister || base == ZR) { + if (scale == TIMES_1) { + AddImmediate(dest, index, disp); + } else { + orr(dest, ZR, Operand(index, LSL, scale)); + AddImmediate(dest, disp); + } } else { - orr(dest, ZR, Operand(src, LSL, scale)); - AddImmediate(dest, dest, value); + add(dest, base, compiler::Operand(index, LSL, scale)); + AddImmediate(dest, disp); } } void SubImmediateSetFlags(Register dest, diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h index d17c0380ccdf..d2131e43ec1a 100644 --- a/runtime/vm/compiler/assembler/assembler_base.h +++ b/runtime/vm/compiler/assembler/assembler_base.h @@ -1093,6 +1093,17 @@ class AssemblerBase : public StackResource { /*Nullability*/ int8_t value, Register scratch); + // [dst] = [base] + ([index] << [scale]) + [disp]. + // + // Base can be kNoRegister (or ZR if available), in which case + // [dst] = [index] << [scale] + [disp] + // with a set of emitted instructions optimized for that case. + virtual void AddScaled(Register dst, + Register base, + Register index, + ScaleFactor scale, + int32_t disp) = 0; + virtual void LoadImmediate(Register dst, target::word imm) = 0; virtual void CompareImmediate(Register reg, diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h index ec36767d1edc..f71a3d5cdcb2 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.h +++ b/runtime/vm/compiler/assembler/assembler_ia32.h @@ -717,14 +717,17 @@ class Assembler : public AssemblerBase { } void AddImmediate(Register dest, Register src, int32_t value); void AddRegisters(Register dest, Register src) { addl(dest, src); } - // [dest] = [src] << [scale] + [value]. void AddScaled(Register dest, - Register src, + Register base, + Register index, ScaleFactor scale, - int32_t value) { - leal(dest, Address(src, scale, value)); + int32_t disp) override { + if (base == kNoRegister) { + leal(dest, Address(index, scale, disp)); + } else { + leal(dest, Address(base, index, scale, disp)); + } } - void SubImmediate(Register reg, const Immediate& imm); void SubRegisters(Register dest, Register src) { subl(dest, src); } void MulImmediate(Register reg, diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h index 622a2cde8c54..2148e37d3847 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv.h +++ b/runtime/vm/compiler/assembler/assembler_riscv.h @@ -1039,16 +1039,21 @@ class Assembler : public MicroAssembler { MulImmediate(dest, dest, imm, width); } void AddRegisters(Register dest, Register src) { add(dest, dest, src); } - // [dest] = [src] << [scale] + [value]. void AddScaled(Register dest, - Register src, + Register base, + Register index, ScaleFactor scale, - int32_t value) { - if (scale == 0) { - AddImmediate(dest, src, value); + int32_t disp) override { + if (base == kNoRegister || base == ZR) { + if (scale == TIMES_1) { + AddImmediate(dest, index, disp); + } else { + slli(dest, index, scale); + AddImmediate(dest, disp); + } } else { - slli(dest, src, scale); - AddImmediate(dest, dest, value); + AddShifted(dest, base, index, scale); + AddImmediate(dest, disp); } } void AddShifted(Register dest, Register base, Register index, intx_t shift); diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h index 9d27699633b6..daa5422b65af 100644 --- a/runtime/vm/compiler/assembler/assembler_x64.h +++ b/runtime/vm/compiler/assembler/assembler_x64.h @@ -784,12 +784,16 @@ class Assembler : public AssemblerBase { AddImmediate(reg, Immediate(value), width); } void AddRegisters(Register dest, Register src) { addq(dest, src); } - // [dest] = [src] << [scale] + [value]. void AddScaled(Register dest, - Register src, + Register base, + Register index, ScaleFactor scale, - int32_t value) { - leaq(dest, Address(src, scale, value)); + int32_t disp) override { + if (base == kNoRegister) { + leaq(dest, Address(index, scale, disp)); + } else { + leaq(dest, Address(base, index, scale, disp)); + } } void AddImmediate(Register dest, Register src, int64_t value); void AddImmediate(const Address& address, const Immediate& imm); diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index b9dfb994943c..4ce820932657 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -7802,6 +7802,98 @@ void StoreFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } } +LocationSummary* CalculateElementAddressInstr::MakeLocationSummary( + Zone* zone, + bool opt) const { + const intptr_t kNumInputs = 3; + const intptr_t kNumTemps = 0; + auto* const summary = new (zone) + LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); + + summary->set_in(kBasePos, Location::RequiresRegister()); + // Only use a Smi constant for the index if multiplying it by the index + // scale would be an int32 constant. + const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale()); + summary->set_in(kIndexPos, LocationRegisterOrSmiConstant( + index(), kMinInt32 >> scale_shift, + kMaxInt32 >> scale_shift)); + // Only use a Smi constant for the offset if it is an int32 constant. + summary->set_in(kOffsetPos, LocationRegisterOrSmiConstant(offset(), kMinInt32, + kMaxInt32)); + // Special case for when both inputs are appropriate constants. + if (summary->in(kIndexPos).IsConstant() && + summary->in(kOffsetPos).IsConstant()) { + const int64_t offset_in_bytes = Utils::AddWithWrapAround( + Utils::MulWithWrapAround(index()->BoundSmiConstant(), + index_scale()), + offset()->BoundSmiConstant()); + if (!Utils::IsInt(32, offset_in_bytes)) { + // The offset in bytes calculated from the index and offset cannot + // fit in a 32-bit immediate, so pass the index as a register instead. + summary->set_in(kIndexPos, Location::RequiresRegister()); + } + } + + // Currently this instruction can only be used in optimized mode as it takes + // and puts untagged values on the stack, and the canonicalization pass should + // always remove no-op uses of this instruction. Flag this for handling if + // this ever changes. + ASSERT(opt && !IsNoop()); + summary->set_out(0, Location::RequiresRegister()); + + return summary; +} + +void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) { + const Register base_reg = locs()->in(kBasePos).reg(); + const Location& index_loc = locs()->in(kIndexPos); + const Location& offset_loc = locs()->in(kOffsetPos); + const Register result_reg = locs()->out(0).reg(); + + ASSERT(!IsNoop()); + + if (index_loc.IsConstant()) { + const int64_t index = Smi::Cast(index_loc.constant()).Value(); + ASSERT(Utils::IsInt(32, index)); + const int64_t scaled_index = index * index_scale(); + ASSERT(Utils::IsInt(32, scaled_index)); + if (offset_loc.IsConstant()) { + const int64_t disp = + scaled_index + Smi::Cast(offset_loc.constant()).Value(); + ASSERT(Utils::IsInt(32, disp)); + __ AddScaled(result_reg, kNoRegister, base_reg, TIMES_1, disp); + } else { + __ AddScaled(result_reg, base_reg, offset_loc.reg(), TIMES_1, + scaled_index); + } + } else { + Register index_reg = index_loc.reg(); + ASSERT(RepresentationUtils::IsUnboxedInteger( + RequiredInputRepresentation(kIndexPos))); + auto scale = ToScaleFactor(index_scale(), /*index_unboxed=*/true); +#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32) + if (scale == TIMES_16) { + COMPILE_ASSERT(kSmiTagShift == 1); + // A ScaleFactor of TIMES_16 is invalid for x86, so box the index as a Smi + // (using the result register to store it to avoid allocating a writable + // register for the index) to reduce the ScaleFactor to TIMES_8. + __ MoveAndSmiTagRegister(result_reg, index_reg); + index_reg = result_reg; + scale = TIMES_8; + } +#endif + if (offset_loc.IsConstant()) { + const intptr_t disp = Smi::Cast(offset_loc.constant()).Value(); + ASSERT(Utils::IsInt(32, disp)); + __ AddScaled(result_reg, base_reg, index_reg, scale, disp); + } else { + // No architecture can do this case in a single instruction. + __ AddScaled(result_reg, base_reg, index_reg, scale, /*disp=*/0); + __ AddRegisters(result_reg, offset_loc.reg()); + } + } +} + const Code& DartReturnInstr::GetReturnStub(FlowGraphCompiler* compiler) const { const Function& function = compiler->parsed_function().function(); ASSERT(function.IsSuspendableFunction()); diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index 93fcb19f9034..4b51a7104d32 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -449,82 +449,6 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler, __ AddImmediate(payload_reg, offset); } -LocationSummary* CalculateElementAddressInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 3; - const intptr_t kNumTemps = 0; - auto* const summary = new (zone) - LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - - summary->set_in(kBasePos, Location::RequiresRegister()); - // Only use a Smi constant for the index if multiplying it by the index - // scale would be an int32 constant. - const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale()); - summary->set_in(kIndexPos, LocationRegisterOrSmiConstant( - index(), kMinInt32 >> scale_shift, - kMaxInt32 >> scale_shift)); - summary->set_in(kOffsetPos, LocationRegisterOrSmiConstant(offset())); - // Special case for when both inputs are appropriate constants. - if (summary->in(kIndexPos).IsConstant() && - summary->in(kOffsetPos).IsConstant()) { - const int64_t offset_in_bytes = Utils::AddWithWrapAround( - Utils::MulWithWrapAround(index()->BoundSmiConstant(), - index_scale()), - offset()->BoundSmiConstant()); - if (!Utils::IsInt(32, offset_in_bytes)) { - // The offset in bytes calculated from the index and offset cannot - // fit in a 32-bit immediate, so pass the index as a register instead. - summary->set_in(kIndexPos, Location::RequiresRegister()); - } - } - - if (IsNoop()) { - summary->set_out(0, Location::SameAsFirstInput()); - } else { - summary->set_out(0, Location::RequiresRegister()); - } - - return summary; -} - -void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - const Register base_reg = locs()->in(kBasePos).reg(); - const Location& index_loc = locs()->in(kIndexPos); - const Location& offset_loc = locs()->in(kOffsetPos); - const Register result_reg = locs()->out(0).reg(); - - if (IsNoop()) { - ASSERT_EQUAL(base_reg, result_reg); - return; - } - - if (index_loc.IsConstant()) { - const intptr_t scaled_index = - Smi::Cast(index_loc.constant()).Value() * index_scale(); - if (offset_loc.IsConstant()) { - const intptr_t offset_in_bytes = - scaled_index + Smi::Cast(offset_loc.constant()).Value(); - __ AddImmediate(result_reg, base_reg, offset_in_bytes); - } else { - __ add(result_reg, base_reg, compiler::Operand(offset_loc.reg())); - // Don't need wrap-around as the index is constant only if multiplying - // it by the scale is an int32. - __ AddImmediate(result_reg, scaled_index); - } - } else { - __ add(result_reg, base_reg, - compiler::Operand(index_loc.reg(), LSL, - Utils::ShiftForPowerOfTwo(index_scale()))); - if (offset_loc.IsConstant()) { - const int32_t offset_value = Smi::Cast(offset_loc.constant()).Value(); - __ AddImmediate(result_reg, offset_value); - } else { - __ AddRegisters(result_reg, offset_loc.reg()); - } - } -} - LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone, bool opt) const { const intptr_t kNumInputs = 1; diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index 222eb07656ce..167c69230927 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -371,70 +371,6 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler, __ AddImmediate(payload_reg, offset); } -LocationSummary* CalculateElementAddressInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 3; - const intptr_t kNumTemps = 0; - auto* const summary = new (zone) - LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - - summary->set_in(kBasePos, Location::RequiresRegister()); - summary->set_in(kIndexPos, Location::RequiresRegister()); - // Only use a Smi constant for the index if multiplying it by the index - // scale would be an int64 constant. - const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale()); - summary->set_in(kIndexPos, LocationRegisterOrSmiConstant( - index(), kMinInt64 >> scale_shift, - kMaxInt64 >> scale_shift)); - // Any possible int64 value is okay as a constant here. - summary->set_in(kOffsetPos, LocationRegisterOrConstant(offset())); - - if (IsNoop()) { - summary->set_out(0, Location::SameAsFirstInput()); - } else { - summary->set_out(0, Location::RequiresRegister()); - } - - return summary; -} - -void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - const Register base_reg = locs()->in(kBasePos).reg(); - const Location& index_loc = locs()->in(kIndexPos); - const Location& offset_loc = locs()->in(kOffsetPos); - const Register result_reg = locs()->out(0).reg(); - - if (IsNoop()) { - ASSERT_EQUAL(base_reg, result_reg); - return; - } - - if (index_loc.IsConstant()) { - const intptr_t scaled_index = - Smi::Cast(index_loc.constant()).Value() * index_scale(); - if (offset_loc.IsConstant()) { - const intptr_t offset_in_bytes = - scaled_index + Smi::Cast(offset_loc.constant()).Value(); - __ AddImmediate(result_reg, base_reg, offset_in_bytes); - } else { - __ add(result_reg, base_reg, compiler::Operand(offset_loc.reg())); - __ AddImmediate(result_reg, scaled_index); - } - } else { - __ add(result_reg, base_reg, - compiler::Operand(index_loc.reg(), LSL, - Utils::ShiftForPowerOfTwo(index_scale()))); - if (offset_loc.IsConstant()) { - const int64_t offset_value = - Integer::Cast(offset_loc.constant()).AsInt64Value(); - __ AddImmediate(result_reg, offset_value); - } else { - __ AddRegisters(result_reg, offset_loc.reg()); - } - } -} - LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone, bool opt) const { const intptr_t kNumInputs = 1; diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index 6fd14d7d20dd..b2657f9c019b 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -250,96 +250,6 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler, __ leal(payload_reg, compiler::Address(array_reg, start_reg, scale, offset)); } -LocationSummary* CalculateElementAddressInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 3; - const intptr_t kNumTemps = 0; - auto* const summary = new (zone) - LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - - summary->set_in(kBasePos, Location::RequiresRegister()); - // Only use a Smi constant for the index if multiplying it by the index - // scale would be an int32 constant. - const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale()); - summary->set_in(kIndexPos, LocationRegisterOrSmiConstant( - index(), kMinInt32 >> scale_shift, - kMaxInt32 >> scale_shift)); - summary->set_in(kOffsetPos, LocationRegisterOrSmiConstant(offset())); - // Special case for when both inputs are appropriate constants. - if (summary->in(kIndexPos).IsConstant() && - summary->in(kOffsetPos).IsConstant()) { - const int64_t offset_in_bytes = Utils::AddWithWrapAround( - Utils::MulWithWrapAround(index()->BoundSmiConstant(), - index_scale()), - offset()->BoundSmiConstant()); - if (!Utils::IsInt(32, offset_in_bytes)) { - // The offset in bytes calculated from the index and offset cannot - // fit in a 32-bit immediate, so pass the index as a register instead. - summary->set_in(kIndexPos, Location::RequiresRegister()); - } - } - - if (IsNoop()) { - summary->set_out(0, Location::SameAsFirstInput()); - } else { - summary->set_out(0, Location::RequiresRegister()); - } - - return summary; -} - -void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - const Register base_reg = locs()->in(kBasePos).reg(); - const Location& index_loc = locs()->in(kIndexPos); - const Location& offset_loc = locs()->in(kOffsetPos); - const Register result_reg = locs()->out(0).reg(); - - if (IsNoop()) { - ASSERT_EQUAL(base_reg, result_reg); - return; - } - - if (index_loc.IsConstant()) { - const intptr_t scaled_index = - Smi::Cast(index_loc.constant()).Value() * index_scale(); - if (offset_loc.IsConstant()) { - const intptr_t offset_in_bytes = - scaled_index + Smi::Cast(offset_loc.constant()).Value(); - __ leal(result_reg, compiler::Address(base_reg, offset_in_bytes)); - } else { - __ leal(result_reg, compiler::Address(base_reg, offset_loc.reg(), TIMES_1, - scaled_index)); - } - } else { - Register index_reg = index_loc.reg(); - bool index_unboxed = RepresentationUtils::IsUnboxedInteger( - RequiredInputRepresentation(kIndexPos)); - ASSERT(index_unboxed); - if (index_scale() == 16) { - COMPILE_ASSERT(kSmiTagShift == 1); - // A ScaleFactor of TIMES_16 is invalid for x86, so box the index as a Smi - // (using the result register to store it to avoid allocating a writable - // register for the index) to reduce the ScaleFactor to TIMES_8. - __ MoveAndSmiTagRegister(result_reg, index_reg); - index_reg = result_reg; - index_unboxed = false; - } - auto const scale = ToScaleFactor(index_scale(), index_unboxed); - if (offset_loc.IsConstant()) { - const int32_t offset_value = Smi::Cast(offset_loc.constant()).Value(); - __ leal(result_reg, - compiler::Address(base_reg, index_reg, scale, offset_value)); - } else { - // compiler::Address(reg, reg, scale, reg) is invalid, so have to do - // as a two-part operation. - __ leal(result_reg, compiler::Address(base_reg, index_reg, scale, - /*disp=*/0)); - __ AddRegisters(result_reg, offset_loc.reg()); - } - } -} - LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone, bool opt) const { const intptr_t kNumInputs = 1; diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc index 47df567523f8..93a42d1a20f6 100644 --- a/runtime/vm/compiler/backend/il_riscv.cc +++ b/runtime/vm/compiler/backend/il_riscv.cc @@ -437,85 +437,6 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler, __ AddImmediate(payload_reg, offset); } -LocationSummary* CalculateElementAddressInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 3; - const intptr_t kNumTemps = 0; - auto* const summary = new (zone) - LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - - summary->set_in(kBasePos, Location::RequiresRegister()); - summary->set_in(kIndexPos, Location::RequiresRegister()); - // Only use a Smi constant for the index if multiplying it by the index - // scale would be an intx constant. - const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale()); - summary->set_in( - kIndexPos, LocationRegisterOrSmiConstant(index(), kMinIntX >> scale_shift, - kMaxIntX >> scale_shift)); -#if XLEN == 32 - summary->set_in(kOffsetPos, LocationRegisterOrSmiConstant(offset())); - // Special case for when both inputs are appropriate constants. - if (summary->in(kIndexPos).IsConstant() && - summary->in(kOffsetPos).IsConstant()) { - const int64_t offset_in_bytes = Utils::AddWithWrapAround( - Utils::MulWithWrapAround(index()->BoundSmiConstant(), - index_scale()), - offset()->BoundSmiConstant()); - if (!Utils::IsInt(32, offset_in_bytes)) { - // The offset in bytes calculated from the index and offset cannot - // fit in a 32-bit immediate, so pass the index as a register instead. - summary->set_in(kIndexPos, Location::RequiresRegister()); - } - } -#else - summary->set_in(kOffsetPos, LocationRegisterOrConstant(offset())); -#endif - - if (IsNoop()) { - summary->set_out(0, Location::SameAsFirstInput()); - } else { - summary->set_out(0, Location::RequiresRegister()); - } - - return summary; -} - -void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - const Register base_reg = locs()->in(kBasePos).reg(); - const Location& index_loc = locs()->in(kIndexPos); - const Location& offset_loc = locs()->in(kOffsetPos); - const Register result_reg = locs()->out(0).reg(); - - if (IsNoop()) { - ASSERT_EQUAL(base_reg, result_reg); - return; - } - - if (index_loc.IsConstant()) { - const intptr_t scaled_index = - Smi::Cast(index_loc.constant()).Value() * index_scale(); - if (offset_loc.IsConstant()) { - const intx_t offset_in_bytes = - scaled_index + Smi::Cast(offset_loc.constant()).Value(); - __ AddImmediate(result_reg, base_reg, offset_in_bytes); - } else { - __ add(result_reg, base_reg, offset_loc.reg()); - __ AddImmediate(result_reg, scaled_index); - } - } else { - __ AddShifted(result_reg, base_reg, index_loc.reg(), - Utils::ShiftForPowerOfTwo(index_scale())); - if (offset_loc.IsConstant()) { - const intx_t offset_value = - Integer::Cast(offset_loc.constant()).AsInt64Value(); - __ AddImmediate(result_reg, offset_value); - } else { - __ AddRegisters(result_reg, offset_loc.reg()); - } - } -} - LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone, bool opt) const { const intptr_t kNumInputs = 1; diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index f817d0c6bd42..942cfee9318f 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -348,101 +348,6 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler, __ leaq(payload_reg, compiler::Address(array_reg, start_reg, scale, offset)); } -LocationSummary* CalculateElementAddressInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 3; - const intptr_t kNumTemps = 0; - auto* const summary = new (zone) - LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - - summary->set_in(kBasePos, Location::RequiresRegister()); - // Only use a Smi constant for the index if multiplying it by the index - // scale would be an int32 constant. - const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale()); - summary->set_in(kIndexPos, LocationRegisterOrSmiConstant( - index(), kMinInt32 >> scale_shift, - kMaxInt32 >> scale_shift)); - // Only use a Smi constant for the offset if it is an int32 constant. - summary->set_in(kOffsetPos, LocationRegisterOrSmiConstant(offset(), kMinInt32, - kMaxInt32)); - // Special case for when both inputs are appropriate constants. - if (summary->in(kIndexPos).IsConstant() && - summary->in(kOffsetPos).IsConstant()) { - const int64_t offset_in_bytes = Utils::AddWithWrapAround( - Utils::MulWithWrapAround(index()->BoundSmiConstant(), - index_scale()), - offset()->BoundSmiConstant()); - if (!Utils::IsInt(32, offset_in_bytes)) { - // The offset in bytes calculated from the index and offset cannot - // fit in a 32-bit immediate, so pass the index as a register instead. - summary->set_in(kIndexPos, Location::RequiresRegister()); - } - } - - if (IsNoop()) { - summary->set_out(0, Location::SameAsFirstInput()); - } else { - summary->set_out(0, Location::RequiresRegister()); - } - - return summary; -} - -void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - const Register base_reg = locs()->in(kBasePos).reg(); - const Location& index_loc = locs()->in(kIndexPos); - const Location& offset_loc = locs()->in(kOffsetPos); - const Register result_reg = locs()->out(0).reg(); - - if (IsNoop()) { - ASSERT_EQUAL(base_reg, result_reg); - return; - } - - if (index_loc.IsConstant()) { - const intptr_t scaled_index = - Smi::Cast(index_loc.constant()).Value() * index_scale(); - ASSERT(Utils::IsInt(32, scaled_index)); - if (offset_loc.IsConstant()) { - const intptr_t offset_in_bytes = - scaled_index + Smi::Cast(offset_loc.constant()).Value(); - ASSERT(Utils::IsInt(32, offset_in_bytes)); - __ leaq(result_reg, compiler::Address(base_reg, offset_in_bytes)); - } else { - __ leaq(result_reg, compiler::Address(base_reg, offset_loc.reg(), TIMES_1, - scaled_index)); - } - } else { - Register index_reg = index_loc.reg(); - bool index_unboxed = RepresentationUtils::IsUnboxedInteger( - RequiredInputRepresentation(kIndexPos)); - ASSERT(index_unboxed); - if (index_scale() == 16) { - COMPILE_ASSERT(kSmiTagShift == 1); - // A ScaleFactor of TIMES_16 is invalid for x86, so box the index as a Smi - // (using the result register to store it to avoid allocating a writable - // register for the index) to reduce the ScaleFactor to TIMES_8. - __ MoveAndSmiTagRegister(result_reg, index_reg); - index_reg = result_reg; - index_unboxed = false; - } - auto const scale = ToScaleFactor(index_scale(), index_unboxed); - if (offset_loc.IsConstant()) { - const intptr_t offset_value = Smi::Cast(offset_loc.constant()).Value(); - ASSERT(Utils::IsInt(32, offset_value)); - __ leaq(result_reg, - compiler::Address(base_reg, index_reg, scale, offset_value)); - } else { - // compiler::Address(reg, reg, scale, reg) is invalid, so have to do - // as a two-part operation. - __ leaq(result_reg, compiler::Address(base_reg, index_reg, scale, - /*disp=*/0)); - __ AddRegisters(result_reg, offset_loc.reg()); - } - } -} - LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone, bool opt) const { const intptr_t kNumInputs = 1; diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc index 0df3b311b51e..89e095073cdb 100644 --- a/runtime/vm/compiler/stub_code_compiler.cc +++ b/runtime/vm/compiler/stub_code_compiler.cc @@ -1339,7 +1339,8 @@ void StubCodeCompiler::GenerateAllocateRecordStub() { const intptr_t fixed_size_plus_alignment_padding = (target::Record::field_offset(0) + target::ObjectAlignment::kObjectAlignment - 1); - __ AddScaled(temp_reg, temp_reg, TIMES_COMPRESSED_HALF_WORD_SIZE, + __ AddScaled(temp_reg, kNoRegister, temp_reg, + TIMES_COMPRESSED_HALF_WORD_SIZE, fixed_size_plus_alignment_padding); __ AndImmediate(temp_reg, -target::ObjectAlignment::kObjectAlignment);