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

Side by Side Diff: src/compiler/arm/code-generator-arm.cc

Issue 2313863003: [arm] Improve Float(32|64)(Max|Min). (Closed)
Patch Set: Created 4 years, 3 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
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | test/cctest/test-assembler-arm.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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/code-generator.h" 5 #include "src/compiler/code-generator.h"
6 6
7 #include "src/arm/macro-assembler-arm.h" 7 #include "src/arm/macro-assembler-arm.h"
8 #include "src/compilation-info.h" 8 #include "src/compilation-info.h"
9 #include "src/compiler/code-generator-impl.h" 9 #include "src/compiler/code-generator-impl.h"
10 #include "src/compiler/gap-resolver.h" 10 #include "src/compiler/gap-resolver.h"
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 Register const index_; 264 Register const index_;
265 int32_t const index_immediate_; // Valid if index_.is(no_reg). 265 int32_t const index_immediate_; // Valid if index_.is(no_reg).
266 Register const value_; 266 Register const value_;
267 Register const scratch0_; 267 Register const scratch0_;
268 Register const scratch1_; 268 Register const scratch1_;
269 RecordWriteMode const mode_; 269 RecordWriteMode const mode_;
270 bool must_save_lr_; 270 bool must_save_lr_;
271 UnwindingInfoWriter* const unwinding_info_writer_; 271 UnwindingInfoWriter* const unwinding_info_writer_;
272 }; 272 };
273 273
274 template <typename T>
275 class OutOfLineFloatMin final : public OutOfLineCode {
276 public:
277 OutOfLineFloatMin(CodeGenerator* gen, T result, T left, T right)
278 : OutOfLineCode(gen), result_(result), left_(left), right_(right) {}
279
280 void Generate() final { __ FloatMinOutOfLine(result_, left_, right_); }
281
282 private:
283 T const result_;
284 T const left_;
285 T const right_;
286 };
287 typedef OutOfLineFloatMin<SwVfpRegister> OutOfLineFloat32Min;
288 typedef OutOfLineFloatMin<DwVfpRegister> OutOfLineFloat64Min;
289
290 template <typename T>
291 class OutOfLineFloatMax final : public OutOfLineCode {
292 public:
293 OutOfLineFloatMax(CodeGenerator* gen, T result, T left, T right)
294 : OutOfLineCode(gen), result_(result), left_(left), right_(right) {}
295
296 void Generate() final { __ FloatMaxOutOfLine(result_, left_, right_); }
297
298 private:
299 T const result_;
300 T const left_;
301 T const right_;
302 };
303 typedef OutOfLineFloatMax<SwVfpRegister> OutOfLineFloat32Max;
304 typedef OutOfLineFloatMax<DwVfpRegister> OutOfLineFloat64Max;
274 305
275 Condition FlagsConditionToCondition(FlagsCondition condition) { 306 Condition FlagsConditionToCondition(FlagsCondition condition) {
276 switch (condition) { 307 switch (condition) {
277 case kEqual: 308 case kEqual:
278 return eq; 309 return eq;
279 case kNotEqual: 310 case kNotEqual:
280 return ne; 311 return ne;
281 case kSignedLessThan: 312 case kSignedLessThan:
282 return lt; 313 return lt;
283 case kSignedGreaterThanOrEqual: 314 case kSignedGreaterThanOrEqual:
(...skipping 1086 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 break; 1401 break;
1371 case kArmVldrF64: 1402 case kArmVldrF64:
1372 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); 1403 __ vldr(i.OutputDoubleRegister(), i.InputOffset());
1373 DCHECK_EQ(LeaveCC, i.OutputSBit()); 1404 DCHECK_EQ(LeaveCC, i.OutputSBit());
1374 break; 1405 break;
1375 case kArmVstrF64: 1406 case kArmVstrF64:
1376 __ vstr(i.InputDoubleRegister(0), i.InputOffset(1)); 1407 __ vstr(i.InputDoubleRegister(0), i.InputOffset(1));
1377 DCHECK_EQ(LeaveCC, i.OutputSBit()); 1408 DCHECK_EQ(LeaveCC, i.OutputSBit());
1378 break; 1409 break;
1379 case kArmFloat32Max: { 1410 case kArmFloat32Max: {
1380 FloatRegister left_reg = i.InputFloat32Register(0); 1411 SwVfpRegister result = i.OutputFloat32Register();
1381 FloatRegister right_reg = i.InputFloat32Register(1); 1412 SwVfpRegister left = i.InputFloat32Register(0);
1382 FloatRegister result_reg = i.OutputFloat32Register(); 1413 SwVfpRegister right = i.InputFloat32Register(1);
1383 Label result_is_nan, return_left, return_right, check_zero, done; 1414 if (left.is(right)) {
1384 __ VFPCompareAndSetFlags(left_reg, right_reg); 1415 __ Move(result, left);
1385 __ b(mi, &return_right);
1386 __ b(gt, &return_left);
1387 __ b(vs, &result_is_nan);
1388 // Left equals right => check for -0.
1389 __ VFPCompareAndSetFlags(left_reg, 0.0);
1390 if (left_reg.is(result_reg) || right_reg.is(result_reg)) {
1391 __ b(ne, &done); // left == right != 0.
1392 } else { 1416 } else {
1393 __ b(ne, &return_left); // left == right != 0. 1417 auto ool = new (zone()) OutOfLineFloat32Max(this, result, left, right);
1418 __ FloatMax(result, left, right, ool->entry());
1419 __ bind(ool->exit());
1394 } 1420 }
1395 // At this point, both left and right are either 0 or -0. 1421 DCHECK_EQ(LeaveCC, i.OutputSBit());
1396 // Since we operate on +0 and/or -0, vadd and vand have the same effect;
1397 // the decision for vadd is easy because vand is a NEON instruction.
1398 __ vadd(result_reg, left_reg, right_reg);
1399 __ b(&done);
1400 __ bind(&result_is_nan);
1401 __ vadd(result_reg, left_reg, right_reg);
1402 __ b(&done);
1403 __ bind(&return_right);
1404 __ Move(result_reg, right_reg);
1405 if (!left_reg.is(result_reg)) __ b(&done);
1406 __ bind(&return_left);
1407 __ Move(result_reg, left_reg);
1408 __ bind(&done);
1409 break; 1422 break;
1410 } 1423 }
1411 case kArmFloat64Max: { 1424 case kArmFloat64Max: {
1412 DwVfpRegister left_reg = i.InputDoubleRegister(0); 1425 DwVfpRegister result = i.OutputDoubleRegister();
1413 DwVfpRegister right_reg = i.InputDoubleRegister(1); 1426 DwVfpRegister left = i.InputDoubleRegister(0);
1414 DwVfpRegister result_reg = i.OutputDoubleRegister(); 1427 DwVfpRegister right = i.InputDoubleRegister(1);
1415 Label result_is_nan, return_left, return_right, check_zero, done; 1428 if (left.is(right)) {
1416 __ VFPCompareAndSetFlags(left_reg, right_reg); 1429 __ Move(result, left);
1417 __ b(mi, &return_right);
1418 __ b(gt, &return_left);
1419 __ b(vs, &result_is_nan);
1420 // Left equals right => check for -0.
1421 __ VFPCompareAndSetFlags(left_reg, 0.0);
1422 if (left_reg.is(result_reg) || right_reg.is(result_reg)) {
1423 __ b(ne, &done); // left == right != 0.
1424 } else { 1430 } else {
1425 __ b(ne, &return_left); // left == right != 0. 1431 auto ool = new (zone()) OutOfLineFloat64Max(this, result, left, right);
1432 __ FloatMax(result, left, right, ool->entry());
1433 __ bind(ool->exit());
1426 } 1434 }
1427 // At this point, both left and right are either 0 or -0. 1435 DCHECK_EQ(LeaveCC, i.OutputSBit());
1428 // Since we operate on +0 and/or -0, vadd and vand have the same effect;
1429 // the decision for vadd is easy because vand is a NEON instruction.
1430 __ vadd(result_reg, left_reg, right_reg);
1431 __ b(&done);
1432 __ bind(&result_is_nan);
1433 __ vadd(result_reg, left_reg, right_reg);
1434 __ b(&done);
1435 __ bind(&return_right);
1436 __ Move(result_reg, right_reg);
1437 if (!left_reg.is(result_reg)) __ b(&done);
1438 __ bind(&return_left);
1439 __ Move(result_reg, left_reg);
1440 __ bind(&done);
1441 break; 1436 break;
1442 } 1437 }
1443 case kArmFloat32Min: { 1438 case kArmFloat32Min: {
1444 FloatRegister left_reg = i.InputFloat32Register(0); 1439 SwVfpRegister result = i.OutputFloat32Register();
1445 FloatRegister right_reg = i.InputFloat32Register(1); 1440 SwVfpRegister left = i.InputFloat32Register(0);
1446 FloatRegister result_reg = i.OutputFloat32Register(); 1441 SwVfpRegister right = i.InputFloat32Register(1);
1447 Label result_is_nan, return_left, return_right, check_zero, done; 1442 if (left.is(right)) {
1448 __ VFPCompareAndSetFlags(left_reg, right_reg); 1443 __ Move(result, left);
1449 __ b(mi, &return_left);
1450 __ b(gt, &return_right);
1451 __ b(vs, &result_is_nan);
1452 // Left equals right => check for -0.
1453 __ VFPCompareAndSetFlags(left_reg, 0.0);
1454 if (left_reg.is(result_reg) || right_reg.is(result_reg)) {
1455 __ b(ne, &done); // left == right != 0.
1456 } else { 1444 } else {
1457 __ b(ne, &return_left); // left == right != 0. 1445 auto ool = new (zone()) OutOfLineFloat32Min(this, result, left, right);
1446 __ FloatMin(result, left, right, ool->entry());
1447 __ bind(ool->exit());
1458 } 1448 }
1459 // At this point, both left and right are either 0 or -0. 1449 DCHECK_EQ(LeaveCC, i.OutputSBit());
1460 // We could use a single 'vorr' instruction here if we had NEON support.
1461 // The algorithm is: -((-L) + (-R)), which in case of L and R being
1462 // different registers is most efficiently expressed as -((-L) - R).
1463 __ vneg(left_reg, left_reg);
1464 if (left_reg.is(right_reg)) {
1465 __ vadd(result_reg, left_reg, right_reg);
1466 } else {
1467 __ vsub(result_reg, left_reg, right_reg);
1468 }
1469 __ vneg(result_reg, result_reg);
1470 __ b(&done);
1471 __ bind(&result_is_nan);
1472 __ vadd(result_reg, left_reg, right_reg);
1473 __ b(&done);
1474 __ bind(&return_right);
1475 __ Move(result_reg, right_reg);
1476 if (!left_reg.is(result_reg)) __ b(&done);
1477 __ bind(&return_left);
1478 __ Move(result_reg, left_reg);
1479 __ bind(&done);
1480 break; 1450 break;
1481 } 1451 }
1482 case kArmFloat64Min: { 1452 case kArmFloat64Min: {
1483 DwVfpRegister left_reg = i.InputDoubleRegister(0); 1453 DwVfpRegister result = i.OutputDoubleRegister();
1484 DwVfpRegister right_reg = i.InputDoubleRegister(1); 1454 DwVfpRegister left = i.InputDoubleRegister(0);
1485 DwVfpRegister result_reg = i.OutputDoubleRegister(); 1455 DwVfpRegister right = i.InputDoubleRegister(1);
1486 Label result_is_nan, return_left, return_right, check_zero, done; 1456 if (left.is(right)) {
1487 __ VFPCompareAndSetFlags(left_reg, right_reg); 1457 __ Move(result, left);
1488 __ b(mi, &return_left);
1489 __ b(gt, &return_right);
1490 __ b(vs, &result_is_nan);
1491 // Left equals right => check for -0.
1492 __ VFPCompareAndSetFlags(left_reg, 0.0);
1493 if (left_reg.is(result_reg) || right_reg.is(result_reg)) {
1494 __ b(ne, &done); // left == right != 0.
1495 } else { 1458 } else {
1496 __ b(ne, &return_left); // left == right != 0. 1459 auto ool = new (zone()) OutOfLineFloat64Min(this, result, left, right);
1460 __ FloatMin(result, left, right, ool->entry());
1461 __ bind(ool->exit());
1497 } 1462 }
1498 // At this point, both left and right are either 0 or -0. 1463 DCHECK_EQ(LeaveCC, i.OutputSBit());
1499 // We could use a single 'vorr' instruction here if we had NEON support.
1500 // The algorithm is: -((-L) + (-R)), which in case of L and R being
1501 // different registers is most efficiently expressed as -((-L) - R).
1502 __ vneg(left_reg, left_reg);
1503 if (left_reg.is(right_reg)) {
1504 __ vadd(result_reg, left_reg, right_reg);
1505 } else {
1506 __ vsub(result_reg, left_reg, right_reg);
1507 }
1508 __ vneg(result_reg, result_reg);
1509 __ b(&done);
1510 __ bind(&result_is_nan);
1511 __ vadd(result_reg, left_reg, right_reg);
1512 __ b(&done);
1513 __ bind(&return_right);
1514 __ Move(result_reg, right_reg);
1515 if (!left_reg.is(result_reg)) __ b(&done);
1516 __ bind(&return_left);
1517 __ Move(result_reg, left_reg);
1518 __ bind(&done);
1519 break; 1464 break;
1520 } 1465 }
1521 case kArmFloat64SilenceNaN: { 1466 case kArmFloat64SilenceNaN: {
1522 DwVfpRegister value = i.InputDoubleRegister(0); 1467 DwVfpRegister value = i.InputDoubleRegister(0);
1523 DwVfpRegister result = i.OutputDoubleRegister(); 1468 DwVfpRegister result = i.OutputDoubleRegister();
1524 __ VFPCanonicalizeNaN(result, value); 1469 __ VFPCanonicalizeNaN(result, value);
1525 break; 1470 break;
1526 } 1471 }
1527 case kArmPush: 1472 case kArmPush:
1528 if (instr->InputAt(0)->IsFPRegister()) { 1473 if (instr->InputAt(0)->IsFPRegister()) {
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
2026 padding_size -= v8::internal::Assembler::kInstrSize; 1971 padding_size -= v8::internal::Assembler::kInstrSize;
2027 } 1972 }
2028 } 1973 }
2029 } 1974 }
2030 1975
2031 #undef __ 1976 #undef __
2032 1977
2033 } // namespace compiler 1978 } // namespace compiler
2034 } // namespace internal 1979 } // namespace internal
2035 } // namespace v8 1980 } // namespace v8
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | test/cctest/test-assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698