Skip to content

Commit c06dd2e

Browse files
mkustermanncommit-bot@chromium.org
authored andcommitted
[VM] Implement UnboxInt64Instr::Canonicalize()
This allows us to convert UnboxInt64Instr's to UnboxedConstantIntrs if the input is a constant. Issue #31798 Change-Id: Ieefd28503059302817baa6f1a463a6e6a9a61398 Reviewed-on: https://dart-review.googlesource.com/33462 Commit-Queue: Martin Kustermann <[email protected]> Reviewed-by: Vyacheslav Egorov <[email protected]>
1 parent 616d02e commit c06dd2e

12 files changed

+276
-268
lines changed

runtime/vm/compiler/backend/flow_graph_compiler.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ class ParallelMoveResolver : public ValueObject {
9393
// Helpers for non-trivial source-destination combinations that cannot
9494
// be handled by a single instruction.
9595
void MoveMemoryToMemory(const Address& dst, const Address& src);
96-
void StoreObject(const Address& dst, const Object& obj);
9796
void Exchange(Register reg, const Address& mem);
9897
void Exchange(const Address& mem1, const Address& mem2);
9998
void Exchange(Register reg, Register base_reg, intptr_t stack_offset);

runtime/vm/compiler/backend/flow_graph_compiler_arm.cc

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,44 +1270,14 @@ void ParallelMoveResolver::EmitMove(int index) {
12701270
}
12711271
} else {
12721272
ASSERT(source.IsConstant());
1273-
const Object& constant = source.constant();
1274-
if (destination.IsRegister()) {
1275-
if (source.constant_instruction()->representation() == kUnboxedInt32) {
1276-
__ LoadImmediate(destination.reg(), Smi::Cast(constant).Value());
1277-
} else {
1278-
__ LoadObject(destination.reg(), constant);
1279-
}
1280-
} else if (destination.IsFpuRegister()) {
1281-
const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
1282-
if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0) &&
1283-
TargetCPUFeatures::neon_supported()) {
1284-
QRegister qdst = destination.fpu_reg();
1285-
__ veorq(qdst, qdst, qdst);
1286-
} else {
1287-
__ LoadObject(TMP, constant);
1288-
__ AddImmediate(TMP, TMP, Double::value_offset() - kHeapObjectTag);
1289-
__ vldrd(dst, Address(TMP, 0));
1290-
}
1291-
} else if (destination.IsDoubleStackSlot()) {
1292-
if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0) &&
1293-
TargetCPUFeatures::neon_supported()) {
1294-
__ veorq(QTMP, QTMP, QTMP);
1295-
} else {
1296-
__ LoadObject(TMP, constant);
1297-
__ AddImmediate(TMP, TMP, Double::value_offset() - kHeapObjectTag);
1298-
__ vldrd(DTMP, Address(TMP, 0));
1299-
}
1300-
const intptr_t dest_offset = destination.ToStackSlotOffset();
1301-
__ StoreDToOffset(DTMP, destination.base_reg(), dest_offset);
1273+
1274+
if (destination.IsFpuRegister() || destination.IsDoubleStackSlot() ||
1275+
destination.IsStackSlot()) {
1276+
ScratchRegisterScope scratch(this, kNoRegister);
1277+
source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
1278+
scratch.reg());
13021279
} else {
1303-
ASSERT(destination.IsStackSlot());
1304-
const intptr_t dest_offset = destination.ToStackSlotOffset();
1305-
if (source.constant_instruction()->representation() == kUnboxedInt32) {
1306-
__ LoadImmediate(TMP, Smi::Cast(constant).Value());
1307-
} else {
1308-
__ LoadObject(TMP, constant);
1309-
}
1310-
__ StoreToOffset(kWord, TMP, destination.base_reg(), dest_offset);
1280+
source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
13111281
}
13121282
}
13131283

@@ -1417,10 +1387,6 @@ void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
14171387
UNREACHABLE();
14181388
}
14191389

1420-
void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
1421-
UNREACHABLE();
1422-
}
1423-
14241390
// Do not call or implement this function. Instead, use the form below that
14251391
// uses an offset from the frame pointer instead of an Address.
14261392
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {

runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,46 +1216,12 @@ void ParallelMoveResolver::EmitMove(int index) {
12161216
}
12171217
} else {
12181218
ASSERT(source.IsConstant());
1219-
const Object& constant = source.constant();
1220-
if (destination.IsRegister()) {
1221-
if (constant.IsSmi() &&
1222-
(source.constant_instruction()->representation() == kUnboxedInt32)) {
1223-
__ LoadImmediate(destination.reg(),
1224-
static_cast<int32_t>(Smi::Cast(constant).Value()));
1225-
} else {
1226-
__ LoadObject(destination.reg(), constant);
1227-
}
1228-
} else if (destination.IsFpuRegister()) {
1229-
const VRegister dst = destination.fpu_reg();
1230-
if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
1231-
__ veor(dst, dst, dst);
1232-
} else {
1233-
ScratchRegisterScope tmp(this, kNoRegister);
1234-
__ LoadObject(tmp.reg(), constant);
1235-
__ LoadDFieldFromOffset(dst, tmp.reg(), Double::value_offset());
1236-
}
1237-
} else if (destination.IsDoubleStackSlot()) {
1238-
if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
1239-
__ veor(VTMP, VTMP, VTMP);
1240-
} else {
1241-
ScratchRegisterScope tmp(this, kNoRegister);
1242-
__ LoadObject(tmp.reg(), constant);
1243-
__ LoadDFieldFromOffset(VTMP, tmp.reg(), Double::value_offset());
1244-
}
1245-
const intptr_t dest_offset = destination.ToStackSlotOffset();
1246-
__ StoreDToOffset(VTMP, destination.base_reg(), dest_offset);
1219+
if (destination.IsStackSlot()) {
1220+
ScratchRegisterScope scratch(this, kNoRegister);
1221+
source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
1222+
scratch.reg());
12471223
} else {
1248-
ASSERT(destination.IsStackSlot());
1249-
const intptr_t dest_offset = destination.ToStackSlotOffset();
1250-
ScratchRegisterScope tmp(this, kNoRegister);
1251-
if (constant.IsSmi() &&
1252-
(source.constant_instruction()->representation() == kUnboxedInt32)) {
1253-
__ LoadImmediate(tmp.reg(),
1254-
static_cast<int32_t>(Smi::Cast(constant).Value()));
1255-
} else {
1256-
__ LoadObject(tmp.reg(), constant);
1257-
}
1258-
__ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset);
1224+
source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
12591225
}
12601226
}
12611227

@@ -1355,10 +1321,6 @@ void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
13551321
UNREACHABLE();
13561322
}
13571323

1358-
void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
1359-
UNREACHABLE();
1360-
}
1361-
13621324
// Do not call or implement this function. Instead, use the form below that
13631325
// uses an offset from the frame pointer instead of an Address.
13641326
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {

runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -433,10 +433,6 @@ void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
433433
UNREACHABLE();
434434
}
435435

436-
void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
437-
UNREACHABLE();
438-
}
439-
440436
// Do not call or implement this function. Instead, use the form below that
441437
// uses an offset from the frame pointer instead of an Address.
442438
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {

runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,56 +1186,7 @@ void ParallelMoveResolver::EmitMove(int index) {
11861186
}
11871187
} else {
11881188
ASSERT(source.IsConstant());
1189-
if (destination.IsRegister()) {
1190-
const Object& constant = source.constant();
1191-
if (constant.IsSmi() && (Smi::Cast(constant).Value() == 0)) {
1192-
__ xorl(destination.reg(), destination.reg());
1193-
} else if (constant.IsSmi() &&
1194-
(source.constant_instruction()->representation() ==
1195-
kUnboxedInt32)) {
1196-
__ movl(destination.reg(), Immediate(Smi::Cast(constant).Value()));
1197-
} else {
1198-
__ LoadObjectSafely(destination.reg(), constant);
1199-
}
1200-
} else if (destination.IsFpuRegister()) {
1201-
const Double& constant = Double::Cast(source.constant());
1202-
uword addr = FlowGraphBuilder::FindDoubleConstant(constant.value());
1203-
if (addr == 0) {
1204-
__ pushl(EAX);
1205-
__ LoadObject(EAX, constant);
1206-
__ movsd(destination.fpu_reg(),
1207-
FieldAddress(EAX, Double::value_offset()));
1208-
__ popl(EAX);
1209-
} else if (Utils::DoublesBitEqual(constant.value(), 0.0)) {
1210-
__ xorps(destination.fpu_reg(), destination.fpu_reg());
1211-
} else {
1212-
__ movsd(destination.fpu_reg(), Address::Absolute(addr));
1213-
}
1214-
} else if (destination.IsDoubleStackSlot()) {
1215-
const Double& constant = Double::Cast(source.constant());
1216-
uword addr = FlowGraphBuilder::FindDoubleConstant(constant.value());
1217-
if (addr == 0) {
1218-
__ pushl(EAX);
1219-
__ LoadObject(EAX, constant);
1220-
__ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
1221-
__ popl(EAX);
1222-
} else if (Utils::DoublesBitEqual(constant.value(), 0.0)) {
1223-
__ xorps(XMM0, XMM0);
1224-
} else {
1225-
__ movsd(XMM0, Address::Absolute(addr));
1226-
}
1227-
__ movsd(destination.ToStackSlotAddress(), XMM0);
1228-
} else {
1229-
ASSERT(destination.IsStackSlot());
1230-
const Object& constant = source.constant();
1231-
if (constant.IsSmi() &&
1232-
(source.constant_instruction()->representation() == kUnboxedInt32)) {
1233-
__ movl(destination.ToStackSlotAddress(),
1234-
Immediate(Smi::Cast(constant).Value()));
1235-
} else {
1236-
StoreObject(destination.ToStackSlotAddress(), source.constant());
1237-
}
1238-
}
1189+
source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
12391190
}
12401191

12411192
move->Eliminate();
@@ -1323,16 +1274,6 @@ void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
13231274
__ movl(dst, ensure_scratch.reg());
13241275
}
13251276

1326-
void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
1327-
if (Assembler::IsSafeSmi(obj) || obj.IsNull()) {
1328-
__ movl(dst, Immediate(reinterpret_cast<int32_t>(obj.raw())));
1329-
} else {
1330-
ScratchRegisterScope ensure_scratch(this, kNoRegister);
1331-
__ LoadObjectSafely(ensure_scratch.reg(), obj);
1332-
__ movl(dst, ensure_scratch.reg());
1333-
}
1334-
}
1335-
13361277
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
13371278
ScratchRegisterScope ensure_scratch(this, reg);
13381279
__ movl(ensure_scratch.reg(), mem);

runtime/vm/compiler/backend/flow_graph_compiler_x64.cc

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,42 +1176,12 @@ void ParallelMoveResolver::EmitMove(int index) {
11761176
}
11771177
} else {
11781178
ASSERT(source.IsConstant());
1179-
const Object& constant = source.constant();
1180-
if (destination.IsRegister()) {
1181-
if (constant.IsSmi() && (Smi::Cast(constant).Value() == 0)) {
1182-
__ xorl(destination.reg(), destination.reg());
1183-
} else if (constant.IsSmi() &&
1184-
(source.constant_instruction()->representation() ==
1185-
kUnboxedInt32)) {
1186-
__ movl(destination.reg(), Immediate(Smi::Cast(constant).Value()));
1187-
} else {
1188-
__ LoadObject(destination.reg(), constant);
1189-
}
1190-
} else if (destination.IsFpuRegister()) {
1191-
if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
1192-
__ xorps(destination.fpu_reg(), destination.fpu_reg());
1193-
} else {
1194-
__ LoadObject(TMP, constant);
1195-
__ movsd(destination.fpu_reg(),
1196-
FieldAddress(TMP, Double::value_offset()));
1197-
}
1198-
} else if (destination.IsDoubleStackSlot()) {
1199-
if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
1200-
__ xorps(XMM0, XMM0);
1201-
} else {
1202-
__ LoadObject(TMP, constant);
1203-
__ movsd(XMM0, FieldAddress(TMP, Double::value_offset()));
1204-
}
1205-
__ movsd(destination.ToStackSlotAddress(), XMM0);
1179+
if (destination.IsFpuRegister() || destination.IsDoubleStackSlot()) {
1180+
ScratchRegisterScope scratch(this, kNoRegister);
1181+
source.constant_instruction()->EmitMoveToLocation(compiler_, destination,
1182+
scratch.reg());
12061183
} else {
1207-
ASSERT(destination.IsStackSlot());
1208-
if (constant.IsSmi() &&
1209-
(source.constant_instruction()->representation() == kUnboxedInt32)) {
1210-
__ movl(destination.ToStackSlotAddress(),
1211-
Immediate(Smi::Cast(constant).Value()));
1212-
} else {
1213-
StoreObject(destination.ToStackSlotAddress(), constant);
1214-
}
1184+
source.constant_instruction()->EmitMoveToLocation(compiler_, destination);
12151185
}
12161186
}
12171187

@@ -1298,10 +1268,6 @@ void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
12981268
__ MoveMemoryToMemory(dst, src);
12991269
}
13001270

1301-
void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
1302-
__ StoreObject(dst, obj);
1303-
}
1304-
13051271
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
13061272
__ Exchange(reg, mem);
13071273
}

runtime/vm/compiler/backend/il.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,6 +2369,33 @@ Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
23692369
return this;
23702370
}
23712371

2372+
Definition* UnboxInt64Instr::Canonicalize(FlowGraph* flow_graph) {
2373+
Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph);
2374+
if (replacement != this) {
2375+
return replacement;
2376+
}
2377+
2378+
// Currently we perform this only on 64-bit architectures and not on simdbc64
2379+
// (on simdbc64 the [UnboxedConstantInstr] handling is only implemented for
2380+
// doubles and causes a bailout for everthing else)
2381+
#if !defined(TARGET_ARCH_DBC)
2382+
if (kBitsPerWord == 64) {
2383+
ConstantInstr* c = value()->definition()->AsConstant();
2384+
if (c != NULL && (c->value().IsSmi() || c->value().IsMint())) {
2385+
UnboxedConstantInstr* uc =
2386+
new UnboxedConstantInstr(c->value(), kUnboxedInt64);
2387+
if (c->range() != NULL) {
2388+
uc->set_range(*c->range());
2389+
}
2390+
flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
2391+
return uc;
2392+
}
2393+
}
2394+
#endif // !defined(TARGET_ARCH_DBC)
2395+
2396+
return this;
2397+
}
2398+
23722399
Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
23732400
if (!HasUses()) return NULL;
23742401

runtime/vm/compiler/backend/il.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,6 +2717,15 @@ class ConstantInstr : public TemplateDefinition<0, NoThrow, Pure> {
27172717

27182718
virtual TokenPosition token_pos() const { return token_pos_; }
27192719

2720+
bool IsUnboxedSignedIntegerConstant() const {
2721+
return representation() == kUnboxedInt32 ||
2722+
representation() == kUnboxedInt64;
2723+
}
2724+
2725+
void EmitMoveToLocation(FlowGraphCompiler* compiler,
2726+
const Location& destination,
2727+
Register tmp = kNoRegister);
2728+
27202729
PRINT_OPERANDS_TO_SUPPORT
27212730

27222731
private:
@@ -5351,6 +5360,8 @@ class UnboxInt64Instr : public UnboxIntegerInstr {
53515360

53525361
virtual void InferRange(RangeAnalysis* analysis, Range* range);
53535362

5363+
virtual Definition* Canonicalize(FlowGraph* flow_graph);
5364+
53545365
DECLARE_INSTRUCTION_NO_BACKEND(UnboxInt64)
53555366

53565367
private:

0 commit comments

Comments
 (0)