Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Side by Side Diff: runtime/vm/intermediate_language_arm64.cc

Issue 300143007: Generate better ARM64 code for indexed loads and stores. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 return kUnboxedFloat32x4; 977 return kUnboxedFloat32x4;
978 case kTypedDataFloat64x2ArrayCid: 978 case kTypedDataFloat64x2ArrayCid:
979 return kUnboxedFloat64x2; 979 return kUnboxedFloat64x2;
980 default: 980 default:
981 UNIMPLEMENTED(); 981 UNIMPLEMENTED();
982 return kTagged; 982 return kTagged;
983 } 983 }
984 } 984 }
985 985
986 986
987 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) {
988 ConstantInstr* constant = value->definition()->AsConstant();
989 if ((constant == NULL) || !constant->value().IsSmi()) {
990 return false;
991 }
992 const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
993 const intptr_t scale = Instance::ElementSizeFor(cid);
994 const int64_t offset = index * scale +
995 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
996 if (!Utils::IsInt(32, offset)) {
997 return false;
998 }
999 return Address::CanHoldOffset(static_cast<int32_t>(offset),
1000 Address::Offset,
1001 Address::OperandSizeFor(cid));
1002 }
1003
1004
987 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, 1005 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate,
988 bool opt) const { 1006 bool opt) const {
989 const intptr_t kNumInputs = 2; 1007 const intptr_t kNumInputs = 2;
990 const intptr_t kNumTemps = 0; 1008 const intptr_t kNumTemps = 0;
991 LocationSummary* locs = new(isolate) LocationSummary( 1009 LocationSummary* locs = new(isolate) LocationSummary(
992 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1010 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
993 locs->set_in(0, Location::RequiresRegister()); 1011 locs->set_in(0, Location::RequiresRegister());
994 // The smi index is either untagged (element size == 1), or it is left smi 1012 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) {
995 // tagged (for all element sizes > 1). 1013 locs->set_in(1, Location::Constant(index()->BoundConstant()));
996 // TODO(regis): Revisit and see if the index can be immediate. 1014 } else {
997 locs->set_in(1, Location::WritableRegister()); 1015 locs->set_in(1, Location::RequiresRegister());
1016 }
998 if ((representation() == kUnboxedDouble) || 1017 if ((representation() == kUnboxedDouble) ||
999 (representation() == kUnboxedFloat32x4) || 1018 (representation() == kUnboxedFloat32x4) ||
1000 (representation() == kUnboxedInt32x4) || 1019 (representation() == kUnboxedInt32x4) ||
1001 (representation() == kUnboxedFloat64x2)) { 1020 (representation() == kUnboxedFloat64x2)) {
1002 locs->set_out(0, Location::RequiresFpuRegister()); 1021 locs->set_out(0, Location::RequiresFpuRegister());
1003 } else { 1022 } else {
1004 locs->set_out(0, Location::RequiresRegister()); 1023 locs->set_out(0, Location::RequiresRegister());
1005 } 1024 }
1006 return locs; 1025 return locs;
1007 } 1026 }
1008 1027
1009 1028
1029 static Address ElementAddressForIntIndex(bool is_external,
1030 intptr_t cid,
1031 intptr_t index_scale,
1032 Register array,
1033 intptr_t index) {
1034 const int64_t offset = index * index_scale +
1035 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
1036 ASSERT(Utils::IsInt(32, offset));
1037 const OperandSize size = Address::OperandSizeFor(cid);
1038 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
1039 return Address(array, static_cast<int32_t>(offset), Address::Offset, size);
1040 }
1041
1042
1043 static Address ElementAddressForRegIndex(Assembler* assembler,
1044 bool is_load,
1045 bool is_external,
1046 intptr_t cid,
1047 intptr_t index_scale,
1048 Register array,
1049 Register index) {
1050 // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
1051 const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
1052 const int32_t offset =
1053 is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
1054 ASSERT(array != TMP);
1055 ASSERT(index != TMP);
1056 const Register base = is_load ? TMP : index;
1057 if ((offset == 0) && (shift == 0)) {
1058 return Address(array, index, UXTX, Address::Unscaled);
1059 } else if (shift < 0) {
1060 ASSERT(shift == -1);
1061 assembler->add(base, array, Operand(index, ASR, 1));
1062 } else {
1063 assembler->add(base, array, Operand(index, LSL, shift));
1064 }
1065 const OperandSize size = Address::OperandSizeFor(cid);
1066 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
1067 return Address(base, offset, Address::Offset, size);
1068 }
1069
1070
1010 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1071 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1072 // The array register points to the backing store for external arrays.
1011 const Register array = locs()->in(0).reg(); 1073 const Register array = locs()->in(0).reg();
1012 ASSERT(locs()->in(1).IsRegister()); // TODO(regis): Revisit. 1074 const Location index = locs()->in(1);
1013 const Register index = locs()->in(1).reg();
1014 1075
1015 Address element_address(kNoRegister, 0); 1076 Address element_address = index.IsRegister()
1016 1077 ? ElementAddressForRegIndex(compiler->assembler(),
1017 // The array register points to the backing store for external arrays. 1078 true, // Load.
1018 intptr_t offset = 0; 1079 IsExternal(), class_id(), index_scale(),
1019 if (!IsExternal()) { 1080 array, index.reg())
1020 ASSERT(this->array()->definition()->representation() == kTagged); 1081 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(),
1021 offset = Instance::DataOffsetFor(class_id()) - kHeapObjectTag; 1082 array, Smi::Cast(index.constant()).Value());
1022 } 1083 // Warning: element_address may use register TMP as base.
1023
1024 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
1025 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
1026 // index is expected to be untagged before accessing.
1027 ASSERT(kSmiTagShift == 1);
1028 switch (index_scale()) {
1029 case 1:
1030 __ add(index, array, Operand(index, ASR, kSmiTagSize));
1031 element_address = Address(index, offset);
1032 break;
1033 case 2:
1034 if (offset != 0) {
1035 __ add(index, array, Operand(index));
1036 element_address = Address(index, offset);
1037 } else {
1038 element_address = Address(array, index, UXTX, Address::Unscaled);
1039 }
1040 break;
1041 case 4:
1042 __ add(index, array, Operand(index, LSL, 1));
1043 element_address = Address(index, offset);
1044 break;
1045 case 8:
1046 __ add(index, array, Operand(index, LSL, 2));
1047 element_address = Address(index, offset);
1048 break;
1049 case 16:
1050 __ add(index, array, Operand(index, LSL, 3));
1051 element_address = Address(index, offset);
1052 break;
1053 default:
1054 UNREACHABLE();
1055 }
1056 1084
1057 if ((representation() == kUnboxedDouble) || 1085 if ((representation() == kUnboxedDouble) ||
1058 (representation() == kUnboxedFloat32x4) || 1086 (representation() == kUnboxedFloat32x4) ||
1059 (representation() == kUnboxedInt32x4) || 1087 (representation() == kUnboxedInt32x4) ||
1060 (representation() == kUnboxedFloat64x2)) { 1088 (representation() == kUnboxedFloat64x2)) {
1061 const VRegister result = locs()->out(0).fpu_reg(); 1089 const VRegister result = locs()->out(0).fpu_reg();
1062 switch (class_id()) { 1090 switch (class_id()) {
1063 case kTypedDataFloat32ArrayCid: 1091 case kTypedDataFloat32ArrayCid:
1064 // Load single precision float. 1092 // Load single precision float.
1065 __ fldrs(result, element_address); 1093 __ fldrs(result, element_address);
1066 break; 1094 break;
1067 case kTypedDataFloat64ArrayCid: 1095 case kTypedDataFloat64ArrayCid:
1068 // Load double precision float. 1096 // Load double precision float.
1069 __ fldrd(result, element_address); 1097 __ fldrd(result, element_address);
1070 break; 1098 break;
1071 case kTypedDataFloat64x2ArrayCid: 1099 case kTypedDataFloat64x2ArrayCid:
1072 case kTypedDataInt32x4ArrayCid: 1100 case kTypedDataInt32x4ArrayCid:
1073 case kTypedDataFloat32x4ArrayCid: 1101 case kTypedDataFloat32x4ArrayCid:
1074 __ fldrq(result, element_address); 1102 __ fldrq(result, element_address);
1075 break; 1103 break;
1104 default:
1105 UNREACHABLE();
1076 } 1106 }
1077 return; 1107 return;
1078 } 1108 }
1079 1109
1080 const Register result = locs()->out(0).reg(); 1110 const Register result = locs()->out(0).reg();
1081 switch (class_id()) { 1111 switch (class_id()) {
1082 case kTypedDataInt8ArrayCid: 1112 case kTypedDataInt8ArrayCid:
1083 ASSERT(index_scale() == 1); 1113 ASSERT(index_scale() == 1);
1084 __ ldr(result, element_address, kByte); 1114 __ ldr(result, element_address, kByte);
1085 __ SmiTag(result); 1115 __ SmiTag(result);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 } 1183 }
1154 1184
1155 1185
1156 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, 1186 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate,
1157 bool opt) const { 1187 bool opt) const {
1158 const intptr_t kNumInputs = 3; 1188 const intptr_t kNumInputs = 3;
1159 const intptr_t kNumTemps = 0; 1189 const intptr_t kNumTemps = 0;
1160 LocationSummary* locs = new(isolate) LocationSummary( 1190 LocationSummary* locs = new(isolate) LocationSummary(
1161 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1191 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1162 locs->set_in(0, Location::RequiresRegister()); 1192 locs->set_in(0, Location::RequiresRegister());
1163 // The smi index is either untagged (element size == 1), or it is left smi 1193 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) {
1164 // tagged (for all element sizes > 1). 1194 locs->set_in(1, Location::Constant(index()->BoundConstant()));
1165 // TODO(regis): Revisit and see if the index can be immediate. 1195 } else {
1166 locs->set_in(1, Location::WritableRegister()); 1196 locs->set_in(1, Location::WritableRegister());
1197 }
1167 switch (class_id()) { 1198 switch (class_id()) {
1168 case kArrayCid: 1199 case kArrayCid:
1169 locs->set_in(2, ShouldEmitStoreBarrier() 1200 locs->set_in(2, ShouldEmitStoreBarrier()
1170 ? Location::WritableRegister() 1201 ? Location::WritableRegister()
1171 : Location::RegisterOrConstant(value())); 1202 : Location::RegisterOrConstant(value()));
1172 break; 1203 break;
1173 case kExternalTypedDataUint8ArrayCid: 1204 case kExternalTypedDataUint8ArrayCid:
1174 case kExternalTypedDataUint8ClampedArrayCid: 1205 case kExternalTypedDataUint8ClampedArrayCid:
1175 case kTypedDataInt8ArrayCid: 1206 case kTypedDataInt8ArrayCid:
1176 case kTypedDataUint8ArrayCid: 1207 case kTypedDataUint8ArrayCid:
(...skipping 18 matching lines...) Expand all
1195 break; 1226 break;
1196 default: 1227 default:
1197 UNREACHABLE(); 1228 UNREACHABLE();
1198 return NULL; 1229 return NULL;
1199 } 1230 }
1200 return locs; 1231 return locs;
1201 } 1232 }
1202 1233
1203 1234
1204 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1235 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1236 // The array register points to the backing store for external arrays.
1205 const Register array = locs()->in(0).reg(); 1237 const Register array = locs()->in(0).reg();
1206 ASSERT(locs()->in(1).IsRegister()); // TODO(regis): Revisit. 1238 const Location index = locs()->in(1);
1207 const Register index = locs()->in(1).reg();
1208 1239
1209 Address element_address(kNoRegister, 0); 1240 Address element_address = index.IsRegister()
1210 1241 ? ElementAddressForRegIndex(compiler->assembler(),
1211 // The array register points to the backing store for external arrays. 1242 false, // Store.
1212 intptr_t offset = 0; 1243 IsExternal(), class_id(), index_scale(),
1213 if (!IsExternal()) { 1244 array, index.reg())
1214 ASSERT(this->array()->definition()->representation() == kTagged); 1245 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(),
1215 offset = Instance::DataOffsetFor(class_id()) - kHeapObjectTag; 1246 array, Smi::Cast(index.constant()).Value());
1216 }
1217
1218 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
1219 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
1220 // index is expected to be untagged before accessing.
1221 ASSERT(kSmiTagShift == 1);
1222 switch (index_scale()) {
1223 case 1: {
1224 __ add(index, array, Operand(index, ASR, kSmiTagSize));
1225 element_address = Address(index, offset);
1226 break;
1227 }
1228 case 2: {
1229 if (offset != 0) {
1230 __ add(index, array, Operand(index));
1231 element_address = Address(index, offset);
1232 } else {
1233 element_address = Address(array, index, UXTX, Address::Unscaled);
1234 }
1235 break;
1236 }
1237 case 4: {
1238 __ add(index, array, Operand(index, LSL, 1));
1239 element_address = Address(index, offset);
1240 break;
1241 }
1242 case 8: {
1243 __ add(index, array, Operand(index, LSL, 2));
1244 element_address = Address(index, offset);
1245 break;
1246 }
1247 case 16: {
1248 __ add(index, array, Operand(index, LSL, 3));
1249 element_address = Address(index, offset);
1250 break;
1251 }
1252 default:
1253 UNREACHABLE();
1254 }
1255 1247
1256 switch (class_id()) { 1248 switch (class_id()) {
1257 case kArrayCid: 1249 case kArrayCid:
1258 if (ShouldEmitStoreBarrier()) { 1250 if (ShouldEmitStoreBarrier()) {
1259 const Register value = locs()->in(2).reg(); 1251 const Register value = locs()->in(2).reg();
1260 __ StoreIntoObject(array, element_address, value); 1252 __ StoreIntoObject(array, element_address, value);
1261 } else if (locs()->in(2).IsConstant()) { 1253 } else if (locs()->in(2).IsConstant()) {
1262 const Object& constant = locs()->in(2).constant(); 1254 const Object& constant = locs()->in(2).constant();
1263 __ StoreIntoObjectNoBarrier(array, element_address, constant); 1255 __ StoreIntoObjectNoBarrier(array, element_address, constant);
1264 } else { 1256 } else {
(...skipping 4144 matching lines...) Expand 10 before | Expand all | Expand 10 after
5409 compiler->GenerateCall(token_pos(), 5401 compiler->GenerateCall(token_pos(),
5410 &label, 5402 &label,
5411 PcDescriptors::kOther, 5403 PcDescriptors::kOther,
5412 locs()); 5404 locs());
5413 __ Drop(ArgumentCount()); // Discard arguments. 5405 __ Drop(ArgumentCount()); // Discard arguments.
5414 } 5406 }
5415 5407
5416 } // namespace dart 5408 } // namespace dart
5417 5409
5418 #endif // defined TARGET_ARCH_ARM64 5410 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698