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

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

Issue 284843004: Adds Math Min/Max to arm64. (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 | « pkg/pkg.status ('k') | tests/lib/lib.status » ('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 830 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 token_pos(), 841 token_pos(),
842 CallFunction(), 842 CallFunction(),
843 kNumberOfArguments, 843 kNumberOfArguments,
844 kNoArgumentNames, 844 kNoArgumentNames,
845 locs()); 845 locs());
846 ASSERT(locs()->out(0).reg() == R0); 846 ASSERT(locs()->out(0).reg() == R0);
847 } 847 }
848 848
849 849
850 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { 850 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const {
851 UNIMPLEMENTED(); 851 const intptr_t kNumInputs = 1;
852 return NULL; 852 return LocationSummary::Make(kNumInputs,
853 Location::RequiresRegister(),
854 LocationSummary::kNoCall);
853 } 855 }
854 856
855 857
856 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 858 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
857 UNIMPLEMENTED(); 859 Register object = locs()->in(0).reg();
860 Register result = locs()->out(0).reg();
861 __ LoadFieldFromOffset(result, object, offset(), PP);
858 } 862 }
859 863
860 864
861 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { 865 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const {
862 const intptr_t kNumInputs = 1; 866 const intptr_t kNumInputs = 1;
863 return LocationSummary::Make(kNumInputs, 867 return LocationSummary::Make(kNumInputs,
864 Location::RequiresRegister(), 868 Location::RequiresRegister(),
865 LocationSummary::kNoCall); 869 LocationSummary::kNoCall);
866 } 870 }
867 871
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 } 1010 }
1007 1011
1008 if (!IsExternal()) { 1012 if (!IsExternal()) {
1009 ASSERT(this->array()->definition()->representation() == kTagged); 1013 ASSERT(this->array()->definition()->representation() == kTagged);
1010 __ AddImmediate(index.reg(), index.reg(), 1014 __ AddImmediate(index.reg(), index.reg(),
1011 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag, PP); 1015 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag, PP);
1012 } 1016 }
1013 element_address = Address(array, index.reg(), UXTX, Address::Unscaled); 1017 element_address = Address(array, index.reg(), UXTX, Address::Unscaled);
1014 1018
1015 if ((representation() == kUnboxedDouble) || 1019 if ((representation() == kUnboxedDouble) ||
1016 (representation() == kUnboxedMint) ||
1017 (representation() == kUnboxedFloat32x4) || 1020 (representation() == kUnboxedFloat32x4) ||
1018 (representation() == kUnboxedInt32x4) || 1021 (representation() == kUnboxedInt32x4) ||
1019 (representation() == kUnboxedFloat64x2)) { 1022 (representation() == kUnboxedFloat64x2)) {
1020 const VRegister result = locs()->out(0).fpu_reg(); 1023 const VRegister result = locs()->out(0).fpu_reg();
1021 switch (class_id()) { 1024 switch (class_id()) {
1022 case kTypedDataInt32ArrayCid:
1023 case kTypedDataUint32ArrayCid:
1024 // TODO(zra): Add when we have simd.
1025 UNIMPLEMENTED();
1026 break;
1027 case kTypedDataFloat32ArrayCid: 1025 case kTypedDataFloat32ArrayCid:
1028 // Load single precision float. 1026 // Load single precision float.
1029 __ fldrs(result, element_address); 1027 __ fldrs(result, element_address);
1030 break; 1028 break;
1031 case kTypedDataFloat64ArrayCid: 1029 case kTypedDataFloat64ArrayCid:
1032 // Load double precision float. 1030 // Load double precision float.
1033 __ fldrd(result, element_address); 1031 __ fldrd(result, element_address);
1034 break; 1032 break;
1035 case kTypedDataFloat64x2ArrayCid: 1033 case kTypedDataFloat64x2ArrayCid:
1036 case kTypedDataInt32x4ArrayCid: 1034 case kTypedDataInt32x4ArrayCid:
1037 case kTypedDataFloat32x4ArrayCid: 1035 case kTypedDataFloat32x4ArrayCid:
1038 // TODO(zra): Add when we have simd. 1036 __ fldrq(result, element_address);
1039 UNIMPLEMENTED();
1040 break; 1037 break;
1041 } 1038 }
1042 return; 1039 return;
1043 } 1040 }
1044 1041
1045 Register result = locs()->out(0).reg(); 1042 Register result = locs()->out(0).reg();
1046 switch (class_id()) { 1043 switch (class_id()) {
1047 case kTypedDataInt8ArrayCid: 1044 case kTypedDataInt8ArrayCid:
1048 ASSERT(index_scale() == 1); 1045 ASSERT(index_scale() == 1);
1049 __ ldr(result, element_address, kByte); 1046 __ ldr(result, element_address, kByte);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 switch (class_id_) { 1089 switch (class_id_) {
1093 case kArrayCid: 1090 case kArrayCid:
1094 case kOneByteStringCid: 1091 case kOneByteStringCid:
1095 case kTypedDataInt8ArrayCid: 1092 case kTypedDataInt8ArrayCid:
1096 case kTypedDataUint8ArrayCid: 1093 case kTypedDataUint8ArrayCid:
1097 case kExternalTypedDataUint8ArrayCid: 1094 case kExternalTypedDataUint8ArrayCid:
1098 case kTypedDataUint8ClampedArrayCid: 1095 case kTypedDataUint8ClampedArrayCid:
1099 case kExternalTypedDataUint8ClampedArrayCid: 1096 case kExternalTypedDataUint8ClampedArrayCid:
1100 case kTypedDataInt16ArrayCid: 1097 case kTypedDataInt16ArrayCid:
1101 case kTypedDataUint16ArrayCid: 1098 case kTypedDataUint16ArrayCid:
1102 return kTagged;
1103 case kTypedDataInt32ArrayCid: 1099 case kTypedDataInt32ArrayCid:
1104 case kTypedDataUint32ArrayCid: 1100 case kTypedDataUint32ArrayCid:
1105 return value()->IsSmiValue() ? kTagged : kUnboxedMint; 1101 return kTagged;
1106 case kTypedDataFloat32ArrayCid: 1102 case kTypedDataFloat32ArrayCid:
1107 case kTypedDataFloat64ArrayCid: 1103 case kTypedDataFloat64ArrayCid:
1108 return kUnboxedDouble; 1104 return kUnboxedDouble;
1109 case kTypedDataFloat32x4ArrayCid: 1105 case kTypedDataFloat32x4ArrayCid:
1110 return kUnboxedFloat32x4; 1106 return kUnboxedFloat32x4;
1111 case kTypedDataInt32x4ArrayCid: 1107 case kTypedDataInt32x4ArrayCid:
1112 return kUnboxedInt32x4; 1108 return kUnboxedInt32x4;
1113 case kTypedDataFloat64x2ArrayCid: 1109 case kTypedDataFloat64x2ArrayCid:
1114 return kUnboxedFloat64x2; 1110 return kUnboxedFloat64x2;
1115 default: 1111 default:
(...skipping 24 matching lines...) Expand all
1140 case kTypedDataInt8ArrayCid: 1136 case kTypedDataInt8ArrayCid:
1141 case kTypedDataUint8ArrayCid: 1137 case kTypedDataUint8ArrayCid:
1142 case kTypedDataUint8ClampedArrayCid: 1138 case kTypedDataUint8ClampedArrayCid:
1143 case kOneByteStringCid: 1139 case kOneByteStringCid:
1144 case kTypedDataInt16ArrayCid: 1140 case kTypedDataInt16ArrayCid:
1145 case kTypedDataUint16ArrayCid: 1141 case kTypedDataUint16ArrayCid:
1146 locs->set_in(2, Location::WritableRegister()); 1142 locs->set_in(2, Location::WritableRegister());
1147 break; 1143 break;
1148 case kTypedDataInt32ArrayCid: 1144 case kTypedDataInt32ArrayCid:
1149 case kTypedDataUint32ArrayCid: 1145 case kTypedDataUint32ArrayCid:
1150 // Mints are stored in Q registers. For smis, use a writable register 1146 locs->set_in(2, Location::WritableRegister());
1151 // because the value must be untagged before storing.
1152 if (value()->IsSmiValue()) {
1153 locs->set_in(2, Location::WritableRegister());
1154 } else {
1155 // TODO(zra): Implement when we add simd loads and stores.
1156 UNIMPLEMENTED();
1157 }
1158 break; 1147 break;
1159 case kTypedDataFloat32ArrayCid: 1148 case kTypedDataFloat32ArrayCid:
1160 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1149 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1161 locs->set_in(2, Location::RequiresFpuRegister()); 1150 locs->set_in(2, Location::RequiresFpuRegister());
1162 break; 1151 break;
1163 case kTypedDataInt32x4ArrayCid: 1152 case kTypedDataInt32x4ArrayCid:
1164 case kTypedDataFloat32x4ArrayCid: 1153 case kTypedDataFloat32x4ArrayCid:
1165 case kTypedDataFloat64x2ArrayCid: 1154 case kTypedDataFloat64x2ArrayCid:
1166 // TODO(zra): Implement when we add simd loads and stores. 1155 locs->set_in(2, Location::RequiresFpuRegister());
1167 UNIMPLEMENTED();
1168 break; 1156 break;
1169 default: 1157 default:
1170 UNREACHABLE(); 1158 UNREACHABLE();
1171 return NULL; 1159 return NULL;
1172 } 1160 }
1173 return locs; 1161 return locs;
1174 } 1162 }
1175 1163
1176 1164
1177 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1165 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 } 1261 }
1274 case kTypedDataInt16ArrayCid: 1262 case kTypedDataInt16ArrayCid:
1275 case kTypedDataUint16ArrayCid: { 1263 case kTypedDataUint16ArrayCid: {
1276 const Register value = locs()->in(2).reg(); 1264 const Register value = locs()->in(2).reg();
1277 __ SmiUntag(value); 1265 __ SmiUntag(value);
1278 __ str(value, element_address, kUnsignedHalfword); 1266 __ str(value, element_address, kUnsignedHalfword);
1279 break; 1267 break;
1280 } 1268 }
1281 case kTypedDataInt32ArrayCid: 1269 case kTypedDataInt32ArrayCid:
1282 case kTypedDataUint32ArrayCid: { 1270 case kTypedDataUint32ArrayCid: {
1283 if (value()->IsSmiValue()) { 1271 const Register value = locs()->in(2).reg();
1284 ASSERT(RequiredInputRepresentation(2) == kTagged); 1272 __ SmiUntag(value);
1285 const Register value = locs()->in(2).reg(); 1273 __ str(value, element_address, kUnsignedWord);
1286 __ SmiUntag(value);
1287 __ str(value, element_address, kUnsignedWord);
1288 } else {
1289 // TODO(zra): Implement when we add simd loads and stores.
1290 UNIMPLEMENTED();
1291 }
1292 break; 1274 break;
1293 } 1275 }
1294 case kTypedDataFloat32ArrayCid: { 1276 case kTypedDataFloat32ArrayCid: {
1295 const VRegister in2 = locs()->in(2).fpu_reg(); 1277 const VRegister in2 = locs()->in(2).fpu_reg();
1296 __ add(index.reg(), index.reg(), Operand(array)); 1278 __ add(index.reg(), index.reg(), Operand(array));
1297 __ fstrs(in2, Address(index.reg())); 1279 __ fstrs(in2, Address(index.reg()));
1298 break; 1280 break;
1299 } 1281 }
1300 case kTypedDataFloat64ArrayCid: { 1282 case kTypedDataFloat64ArrayCid: {
1301 const VRegister in2 = locs()->in(2).fpu_reg(); 1283 const VRegister in2 = locs()->in(2).fpu_reg();
1302 __ add(index.reg(), index.reg(), Operand(array)); 1284 __ add(index.reg(), index.reg(), Operand(array));
1303 __ StoreDToOffset(in2, index.reg(), 0, PP); 1285 __ StoreDToOffset(in2, index.reg(), 0, PP);
1304 break; 1286 break;
1305 } 1287 }
1306 case kTypedDataFloat64x2ArrayCid: 1288 case kTypedDataFloat64x2ArrayCid:
1307 case kTypedDataInt32x4ArrayCid: 1289 case kTypedDataInt32x4ArrayCid:
1308 case kTypedDataFloat32x4ArrayCid: { 1290 case kTypedDataFloat32x4ArrayCid: {
1309 // TODO(zra): Implement when we add simd loads and stores. 1291 const VRegister in2 = locs()->in(2).fpu_reg();
1310 UNIMPLEMENTED(); 1292 __ add(index.reg(), index.reg(), Operand(array));
1293 __ StoreQToOffset(in2, index.reg(), 0, PP);
1311 break; 1294 break;
1312 } 1295 }
1313 default: 1296 default:
1314 UNREACHABLE(); 1297 UNREACHABLE();
1315 } 1298 }
1316 } 1299 }
1317 1300
1318 1301
1319 static void LoadValueCid(FlowGraphCompiler* compiler, 1302 static void LoadValueCid(FlowGraphCompiler* compiler,
1320 Register value_cid_reg, 1303 Register value_cid_reg,
(...skipping 2132 matching lines...) Expand 10 before | Expand all | Expand 10 after
3453 __ fmuld(result, val, val); 3436 __ fmuld(result, val, val);
3454 } else { 3437 } else {
3455 ASSERT((kind() == MathUnaryInstr::kSin) || 3438 ASSERT((kind() == MathUnaryInstr::kSin) ||
3456 (kind() == MathUnaryInstr::kCos)); 3439 (kind() == MathUnaryInstr::kCos));
3457 __ CallRuntime(TargetFunction(), InputCount()); 3440 __ CallRuntime(TargetFunction(), InputCount());
3458 } 3441 }
3459 } 3442 }
3460 3443
3461 3444
3462 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { 3445 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const {
3463 UNIMPLEMENTED(); 3446 if (result_cid() == kDoubleCid) {
3464 return NULL; 3447 const intptr_t kNumInputs = 2;
3448 const intptr_t kNumTemps = 0;
3449 LocationSummary* summary =
3450 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3451 summary->set_in(0, Location::RequiresFpuRegister());
3452 summary->set_in(1, Location::RequiresFpuRegister());
3453 // Reuse the left register so that code can be made shorter.
3454 summary->set_out(0, Location::SameAsFirstInput());
3455 return summary;
3456 }
3457 ASSERT(result_cid() == kSmiCid);
3458 const intptr_t kNumInputs = 2;
3459 const intptr_t kNumTemps = 0;
3460 LocationSummary* summary =
3461 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3462 summary->set_in(0, Location::RequiresRegister());
3463 summary->set_in(1, Location::RequiresRegister());
3464 // Reuse the left register so that code can be made shorter.
3465 summary->set_out(0, Location::SameAsFirstInput());
3466 return summary;
3465 } 3467 }
3466 3468
3467 3469
3468 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3470 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3469 UNIMPLEMENTED(); 3471 ASSERT((op_kind() == MethodRecognizer::kMathMin) ||
3472 (op_kind() == MethodRecognizer::kMathMax));
3473 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin);
3474 if (result_cid() == kDoubleCid) {
3475 Label done, returns_nan, are_equal;
3476 const VRegister left = locs()->in(0).fpu_reg();
3477 const VRegister right = locs()->in(1).fpu_reg();
3478 const VRegister result = locs()->out(0).fpu_reg();
3479 __ fcmpd(left, right);
3480 __ b(&returns_nan, VS);
3481 __ b(&are_equal, EQ);
3482 const Condition double_condition =
3483 is_min ? TokenKindToDoubleCondition(Token::kLTE)
3484 : TokenKindToDoubleCondition(Token::kGTE);
3485 ASSERT(left == result);
3486 __ b(&done, double_condition);
3487 __ fmovdd(result, right);
3488 __ b(&done);
3489
3490 __ Bind(&returns_nan);
3491 __ LoadDImmediate(result, NAN, PP);
3492 __ b(&done);
3493
3494 __ Bind(&are_equal);
3495 // Check for negative zero: -0.0 is equal 0.0 but min or max must return
3496 // -0.0 or 0.0 respectively.
3497 // Check for negative left value (get the sign bit):
3498 // - min -> left is negative ? left : right.
3499 // - max -> left is negative ? right : left
3500 // Check the sign bit.
3501 __ fmovrd(TMP, left); // Sign bit is in bit 63 of TMP.
3502 __ CompareImmediate(TMP, 0, PP);
3503 if (is_min) {
3504 ASSERT(left == result);
3505 __ b(&done, LT);
3506 __ fmovdd(result, right);
3507 } else {
3508 __ b(&done, GE);
3509 __ fmovdd(result, right);
3510 ASSERT(left == result);
3511 }
3512 __ Bind(&done);
3513 return;
3514 }
3515
3516 ASSERT(result_cid() == kSmiCid);
3517 Register left = locs()->in(0).reg();
3518 Register right = locs()->in(1).reg();
3519 Register result = locs()->out(0).reg();
3520 __ CompareRegisters(left, right);
3521 ASSERT(result == left);
3522 if (is_min) {
3523 __ csel(result, right, left, GT);
3524 } else {
3525 __ csel(result, right, left, LT);
3526 }
3470 } 3527 }
3471 3528
3472 3529
3473 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { 3530 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const {
3474 const intptr_t kNumInputs = 1; 3531 const intptr_t kNumInputs = 1;
3475 const intptr_t kNumTemps = 0; 3532 const intptr_t kNumTemps = 0;
3476 LocationSummary* summary = 3533 LocationSummary* summary =
3477 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3534 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3478 summary->set_in(0, Location::RequiresRegister()); 3535 summary->set_in(0, Location::RequiresRegister());
3479 // We make use of 3-operand instructions by not requiring result register 3536 // We make use of 3-operand instructions by not requiring result register
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after
4376 compiler->GenerateCall(token_pos(), 4433 compiler->GenerateCall(token_pos(),
4377 &label, 4434 &label,
4378 PcDescriptors::kOther, 4435 PcDescriptors::kOther,
4379 locs()); 4436 locs());
4380 __ Drop(ArgumentCount()); // Discard arguments. 4437 __ Drop(ArgumentCount()); // Discard arguments.
4381 } 4438 }
4382 4439
4383 } // namespace dart 4440 } // namespace dart
4384 4441
4385 #endif // defined TARGET_ARCH_ARM64 4442 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « pkg/pkg.status ('k') | tests/lib/lib.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698