Skip to content

Commit 324ba0c

Browse files
sstricklCommit Queue
authored andcommitted
[vm/compiler] Extend Assembler::AddScaled to take a base register.
Add an additional base argument to Assembler::AddScaled so it now computes: dest <- base + (index << scale) + offset If base is kNoRegister (or ZR when available), then it emits instructions optimized for computing: dest <- (index << scale) + offset (i.e., its previous implementation) Add AddScaled to AssemblerBase to ensure the same interface across all architectures. Rework the backend of CalculateElementAddress to use AddScaled appropriately, which unifies it across architectures. TEST=ci (refactoring) Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-simriscv64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-linux-debug-ia32-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-linux-debug-simriscv64-try,vm-mac-debug-arm64-try,vm-aot-mac-release-arm64-try Change-Id: I33c8f99604b68360f10b79050bd66ceb9d65ac9b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370504 Commit-Queue: Tess Strickland <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 9544fe9 commit 324ba0c

File tree

14 files changed

+158
-437
lines changed

14 files changed

+158
-437
lines changed

runtime/vm/compiler/assembler/assembler_arm.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3539,9 +3539,8 @@ void Assembler::LoadAllocationTracingStateAddress(Register dest, Register cid) {
35393539
ldr(dest,
35403540
Address(dest,
35413541
target::ClassTable::allocation_tracing_state_table_offset()));
3542-
AddScaled(cid, cid, TIMES_1,
3542+
AddScaled(dest, dest, cid, TIMES_1,
35433543
target::ClassTable::AllocationTracingStateSlotOffsetFor(0));
3544-
AddRegisters(dest, cid);
35453544
}
35463545

35473546
void Assembler::LoadAllocationTracingStateAddress(Register dest, intptr_t cid) {

runtime/vm/compiler/assembler/assembler_arm.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -832,16 +832,21 @@ class Assembler : public AssemblerBase {
832832
void AddRegisters(Register dest, Register src) {
833833
add(dest, dest, Operand(src));
834834
}
835-
// [dest] = [src] << [scale] + [value].
836835
void AddScaled(Register dest,
837-
Register src,
836+
Register base,
837+
Register index,
838838
ScaleFactor scale,
839-
int32_t value) {
840-
if (scale == 0) {
841-
AddImmediate(dest, src, value);
839+
int32_t disp) override {
840+
if (base == kNoRegister) {
841+
if (scale == TIMES_1) {
842+
AddImmediate(dest, index, disp);
843+
} else {
844+
Lsl(dest, index, Operand(scale));
845+
AddImmediate(dest, disp);
846+
}
842847
} else {
843-
Lsl(dest, src, Operand(scale));
844-
AddImmediate(dest, dest, value);
848+
add(dest, base, compiler::Operand(index, LSL, scale));
849+
AddImmediate(dest, disp);
845850
}
846851
}
847852
void SubImmediate(Register rd,

runtime/vm/compiler/assembler/assembler_arm64.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,16 +1784,21 @@ class Assembler : public AssemblerBase {
17841784
void AddRegisters(Register dest, Register src) {
17851785
add(dest, dest, Operand(src));
17861786
}
1787-
// [dest] = [src] << [scale] + [value].
17881787
void AddScaled(Register dest,
1789-
Register src,
1788+
Register base,
1789+
Register index,
17901790
ScaleFactor scale,
1791-
int32_t value) {
1792-
if (scale == 0) {
1793-
AddImmediate(dest, src, value);
1791+
int32_t disp) override {
1792+
if (base == kNoRegister || base == ZR) {
1793+
if (scale == TIMES_1) {
1794+
AddImmediate(dest, index, disp);
1795+
} else {
1796+
orr(dest, ZR, Operand(index, LSL, scale));
1797+
AddImmediate(dest, disp);
1798+
}
17941799
} else {
1795-
orr(dest, ZR, Operand(src, LSL, scale));
1796-
AddImmediate(dest, dest, value);
1800+
add(dest, base, compiler::Operand(index, LSL, scale));
1801+
AddImmediate(dest, disp);
17971802
}
17981803
}
17991804
void SubImmediateSetFlags(Register dest,

runtime/vm/compiler/assembler/assembler_base.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,17 @@ class AssemblerBase : public StackResource {
10931093
/*Nullability*/ int8_t value,
10941094
Register scratch);
10951095

1096+
// [dst] = [base] + ([index] << [scale]) + [disp].
1097+
//
1098+
// Base can be kNoRegister (or ZR if available), in which case
1099+
// [dst] = [index] << [scale] + [disp]
1100+
// with a set of emitted instructions optimized for that case.
1101+
virtual void AddScaled(Register dst,
1102+
Register base,
1103+
Register index,
1104+
ScaleFactor scale,
1105+
int32_t disp) = 0;
1106+
10961107
virtual void LoadImmediate(Register dst, target::word imm) = 0;
10971108

10981109
virtual void CompareImmediate(Register reg,

runtime/vm/compiler/assembler/assembler_ia32.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -717,14 +717,17 @@ class Assembler : public AssemblerBase {
717717
}
718718
void AddImmediate(Register dest, Register src, int32_t value);
719719
void AddRegisters(Register dest, Register src) { addl(dest, src); }
720-
// [dest] = [src] << [scale] + [value].
721720
void AddScaled(Register dest,
722-
Register src,
721+
Register base,
722+
Register index,
723723
ScaleFactor scale,
724-
int32_t value) {
725-
leal(dest, Address(src, scale, value));
724+
int32_t disp) override {
725+
if (base == kNoRegister) {
726+
leal(dest, Address(index, scale, disp));
727+
} else {
728+
leal(dest, Address(base, index, scale, disp));
729+
}
726730
}
727-
728731
void SubImmediate(Register reg, const Immediate& imm);
729732
void SubRegisters(Register dest, Register src) { subl(dest, src); }
730733
void MulImmediate(Register reg,

runtime/vm/compiler/assembler/assembler_riscv.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,16 +1039,21 @@ class Assembler : public MicroAssembler {
10391039
MulImmediate(dest, dest, imm, width);
10401040
}
10411041
void AddRegisters(Register dest, Register src) { add(dest, dest, src); }
1042-
// [dest] = [src] << [scale] + [value].
10431042
void AddScaled(Register dest,
1044-
Register src,
1043+
Register base,
1044+
Register index,
10451045
ScaleFactor scale,
1046-
int32_t value) {
1047-
if (scale == 0) {
1048-
AddImmediate(dest, src, value);
1046+
int32_t disp) override {
1047+
if (base == kNoRegister || base == ZR) {
1048+
if (scale == TIMES_1) {
1049+
AddImmediate(dest, index, disp);
1050+
} else {
1051+
slli(dest, index, scale);
1052+
AddImmediate(dest, disp);
1053+
}
10491054
} else {
1050-
slli(dest, src, scale);
1051-
AddImmediate(dest, dest, value);
1055+
AddShifted(dest, base, index, scale);
1056+
AddImmediate(dest, disp);
10521057
}
10531058
}
10541059
void AddShifted(Register dest, Register base, Register index, intx_t shift);

runtime/vm/compiler/assembler/assembler_x64.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -784,12 +784,16 @@ class Assembler : public AssemblerBase {
784784
AddImmediate(reg, Immediate(value), width);
785785
}
786786
void AddRegisters(Register dest, Register src) { addq(dest, src); }
787-
// [dest] = [src] << [scale] + [value].
788787
void AddScaled(Register dest,
789-
Register src,
788+
Register base,
789+
Register index,
790790
ScaleFactor scale,
791-
int32_t value) {
792-
leaq(dest, Address(src, scale, value));
791+
int32_t disp) override {
792+
if (base == kNoRegister) {
793+
leaq(dest, Address(index, scale, disp));
794+
} else {
795+
leaq(dest, Address(base, index, scale, disp));
796+
}
793797
}
794798
void AddImmediate(Register dest, Register src, int64_t value);
795799
void AddImmediate(const Address& address, const Immediate& imm);

runtime/vm/compiler/backend/il.cc

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7802,6 +7802,98 @@ void StoreFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
78027802
}
78037803
}
78047804

7805+
LocationSummary* CalculateElementAddressInstr::MakeLocationSummary(
7806+
Zone* zone,
7807+
bool opt) const {
7808+
const intptr_t kNumInputs = 3;
7809+
const intptr_t kNumTemps = 0;
7810+
auto* const summary = new (zone)
7811+
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
7812+
7813+
summary->set_in(kBasePos, Location::RequiresRegister());
7814+
// Only use a Smi constant for the index if multiplying it by the index
7815+
// scale would be an int32 constant.
7816+
const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale());
7817+
summary->set_in(kIndexPos, LocationRegisterOrSmiConstant(
7818+
index(), kMinInt32 >> scale_shift,
7819+
kMaxInt32 >> scale_shift));
7820+
// Only use a Smi constant for the offset if it is an int32 constant.
7821+
summary->set_in(kOffsetPos, LocationRegisterOrSmiConstant(offset(), kMinInt32,
7822+
kMaxInt32));
7823+
// Special case for when both inputs are appropriate constants.
7824+
if (summary->in(kIndexPos).IsConstant() &&
7825+
summary->in(kOffsetPos).IsConstant()) {
7826+
const int64_t offset_in_bytes = Utils::AddWithWrapAround<int64_t>(
7827+
Utils::MulWithWrapAround<int64_t>(index()->BoundSmiConstant(),
7828+
index_scale()),
7829+
offset()->BoundSmiConstant());
7830+
if (!Utils::IsInt(32, offset_in_bytes)) {
7831+
// The offset in bytes calculated from the index and offset cannot
7832+
// fit in a 32-bit immediate, so pass the index as a register instead.
7833+
summary->set_in(kIndexPos, Location::RequiresRegister());
7834+
}
7835+
}
7836+
7837+
// Currently this instruction can only be used in optimized mode as it takes
7838+
// and puts untagged values on the stack, and the canonicalization pass should
7839+
// always remove no-op uses of this instruction. Flag this for handling if
7840+
// this ever changes.
7841+
ASSERT(opt && !IsNoop());
7842+
summary->set_out(0, Location::RequiresRegister());
7843+
7844+
return summary;
7845+
}
7846+
7847+
void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
7848+
const Register base_reg = locs()->in(kBasePos).reg();
7849+
const Location& index_loc = locs()->in(kIndexPos);
7850+
const Location& offset_loc = locs()->in(kOffsetPos);
7851+
const Register result_reg = locs()->out(0).reg();
7852+
7853+
ASSERT(!IsNoop());
7854+
7855+
if (index_loc.IsConstant()) {
7856+
const int64_t index = Smi::Cast(index_loc.constant()).Value();
7857+
ASSERT(Utils::IsInt(32, index));
7858+
const int64_t scaled_index = index * index_scale();
7859+
ASSERT(Utils::IsInt(32, scaled_index));
7860+
if (offset_loc.IsConstant()) {
7861+
const int64_t disp =
7862+
scaled_index + Smi::Cast(offset_loc.constant()).Value();
7863+
ASSERT(Utils::IsInt(32, disp));
7864+
__ AddScaled(result_reg, kNoRegister, base_reg, TIMES_1, disp);
7865+
} else {
7866+
__ AddScaled(result_reg, base_reg, offset_loc.reg(), TIMES_1,
7867+
scaled_index);
7868+
}
7869+
} else {
7870+
Register index_reg = index_loc.reg();
7871+
ASSERT(RepresentationUtils::IsUnboxedInteger(
7872+
RequiredInputRepresentation(kIndexPos)));
7873+
auto scale = ToScaleFactor(index_scale(), /*index_unboxed=*/true);
7874+
#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
7875+
if (scale == TIMES_16) {
7876+
COMPILE_ASSERT(kSmiTagShift == 1);
7877+
// A ScaleFactor of TIMES_16 is invalid for x86, so box the index as a Smi
7878+
// (using the result register to store it to avoid allocating a writable
7879+
// register for the index) to reduce the ScaleFactor to TIMES_8.
7880+
__ MoveAndSmiTagRegister(result_reg, index_reg);
7881+
index_reg = result_reg;
7882+
scale = TIMES_8;
7883+
}
7884+
#endif
7885+
if (offset_loc.IsConstant()) {
7886+
const intptr_t disp = Smi::Cast(offset_loc.constant()).Value();
7887+
ASSERT(Utils::IsInt(32, disp));
7888+
__ AddScaled(result_reg, base_reg, index_reg, scale, disp);
7889+
} else {
7890+
// No architecture can do this case in a single instruction.
7891+
__ AddScaled(result_reg, base_reg, index_reg, scale, /*disp=*/0);
7892+
__ AddRegisters(result_reg, offset_loc.reg());
7893+
}
7894+
}
7895+
}
7896+
78057897
const Code& DartReturnInstr::GetReturnStub(FlowGraphCompiler* compiler) const {
78067898
const Function& function = compiler->parsed_function().function();
78077899
ASSERT(function.IsSuspendableFunction());

runtime/vm/compiler/backend/il_arm.cc

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -449,82 +449,6 @@ void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler,
449449
__ AddImmediate(payload_reg, offset);
450450
}
451451

452-
LocationSummary* CalculateElementAddressInstr::MakeLocationSummary(
453-
Zone* zone,
454-
bool opt) const {
455-
const intptr_t kNumInputs = 3;
456-
const intptr_t kNumTemps = 0;
457-
auto* const summary = new (zone)
458-
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
459-
460-
summary->set_in(kBasePos, Location::RequiresRegister());
461-
// Only use a Smi constant for the index if multiplying it by the index
462-
// scale would be an int32 constant.
463-
const intptr_t scale_shift = Utils::ShiftForPowerOfTwo(index_scale());
464-
summary->set_in(kIndexPos, LocationRegisterOrSmiConstant(
465-
index(), kMinInt32 >> scale_shift,
466-
kMaxInt32 >> scale_shift));
467-
summary->set_in(kOffsetPos, LocationRegisterOrSmiConstant(offset()));
468-
// Special case for when both inputs are appropriate constants.
469-
if (summary->in(kIndexPos).IsConstant() &&
470-
summary->in(kOffsetPos).IsConstant()) {
471-
const int64_t offset_in_bytes = Utils::AddWithWrapAround<int64_t>(
472-
Utils::MulWithWrapAround<int64_t>(index()->BoundSmiConstant(),
473-
index_scale()),
474-
offset()->BoundSmiConstant());
475-
if (!Utils::IsInt(32, offset_in_bytes)) {
476-
// The offset in bytes calculated from the index and offset cannot
477-
// fit in a 32-bit immediate, so pass the index as a register instead.
478-
summary->set_in(kIndexPos, Location::RequiresRegister());
479-
}
480-
}
481-
482-
if (IsNoop()) {
483-
summary->set_out(0, Location::SameAsFirstInput());
484-
} else {
485-
summary->set_out(0, Location::RequiresRegister());
486-
}
487-
488-
return summary;
489-
}
490-
491-
void CalculateElementAddressInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
492-
const Register base_reg = locs()->in(kBasePos).reg();
493-
const Location& index_loc = locs()->in(kIndexPos);
494-
const Location& offset_loc = locs()->in(kOffsetPos);
495-
const Register result_reg = locs()->out(0).reg();
496-
497-
if (IsNoop()) {
498-
ASSERT_EQUAL(base_reg, result_reg);
499-
return;
500-
}
501-
502-
if (index_loc.IsConstant()) {
503-
const intptr_t scaled_index =
504-
Smi::Cast(index_loc.constant()).Value() * index_scale();
505-
if (offset_loc.IsConstant()) {
506-
const intptr_t offset_in_bytes =
507-
scaled_index + Smi::Cast(offset_loc.constant()).Value();
508-
__ AddImmediate(result_reg, base_reg, offset_in_bytes);
509-
} else {
510-
__ add(result_reg, base_reg, compiler::Operand(offset_loc.reg()));
511-
// Don't need wrap-around as the index is constant only if multiplying
512-
// it by the scale is an int32.
513-
__ AddImmediate(result_reg, scaled_index);
514-
}
515-
} else {
516-
__ add(result_reg, base_reg,
517-
compiler::Operand(index_loc.reg(), LSL,
518-
Utils::ShiftForPowerOfTwo(index_scale())));
519-
if (offset_loc.IsConstant()) {
520-
const int32_t offset_value = Smi::Cast(offset_loc.constant()).Value();
521-
__ AddImmediate(result_reg, offset_value);
522-
} else {
523-
__ AddRegisters(result_reg, offset_loc.reg());
524-
}
525-
}
526-
}
527-
528452
LocationSummary* MoveArgumentInstr::MakeLocationSummary(Zone* zone,
529453
bool opt) const {
530454
const intptr_t kNumInputs = 1;

0 commit comments

Comments
 (0)