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

Side by Side Diff: test/cctest/test-assembler-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/compiler/arm/code-generator-arm.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <iostream> // NOLINT(readability/streams) 28 #include <iostream> // NOLINT(readability/streams)
29 29
30 #include "src/v8.h" 30 #include "src/v8.h"
31 #include "test/cctest/cctest.h" 31 #include "test/cctest/cctest.h"
32 32
33 #include "src/arm/assembler-arm-inl.h"
34 #include "src/arm/simulator-arm.h" 33 #include "src/arm/simulator-arm.h"
35 #include "src/base/utils/random-number-generator.h" 34 #include "src/base/utils/random-number-generator.h"
36 #include "src/disassembler.h" 35 #include "src/disassembler.h"
37 #include "src/factory.h" 36 #include "src/factory.h"
37 #include "src/macro-assembler.h"
38 #include "src/ostreams.h" 38 #include "src/ostreams.h"
39 39
40 using namespace v8::base; 40 using namespace v8::base;
41 using namespace v8::internal; 41 using namespace v8::internal;
42 42
43 43
44 // Define these function prototypes to match JSEntryFunction in execution.cc. 44 // Define these function prototypes to match JSEntryFunction in execution.cc.
45 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); 45 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
46 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); 46 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
47 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); 47 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
(...skipping 2327 matching lines...) Expand 10 before | Expand all | Expand 10 after
2375 CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail); 2375 CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail);
2376 CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass); 2376 CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass);
2377 CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail); 2377 CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail);
2378 CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass); 2378 CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass);
2379 2379
2380 #undef CHECK_VSEL 2380 #undef CHECK_VSEL
2381 } 2381 }
2382 } 2382 }
2383 2383
2384 TEST(ARMv8_vminmax_f64) { 2384 TEST(ARMv8_vminmax_f64) {
2385 // Test the vsel floating point instructions. 2385 // Test the vminnm and vmaxnm floating point instructions.
2386 CcTest::InitializeVM(); 2386 CcTest::InitializeVM();
2387 Isolate* isolate = CcTest::i_isolate(); 2387 Isolate* isolate = CcTest::i_isolate();
2388 HandleScope scope(isolate); 2388 HandleScope scope(isolate);
2389 2389
2390 Assembler assm(isolate, NULL, 0); 2390 Assembler assm(isolate, NULL, 0);
2391 2391
2392 struct Inputs { 2392 struct Inputs {
2393 double left_; 2393 double left_;
2394 double right_; 2394 double right_;
2395 }; 2395 };
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2457 CHECK_VMINMAX(0.0, nan_a, 0.0, 0.0); 2457 CHECK_VMINMAX(0.0, nan_a, 0.0, 0.0);
2458 CHECK_VMINMAX(nan_a, 0.0, 0.0, 0.0); 2458 CHECK_VMINMAX(nan_a, 0.0, 0.0, 0.0);
2459 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); 2459 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a);
2460 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); 2460 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b);
2461 2461
2462 #undef CHECK_VMINMAX 2462 #undef CHECK_VMINMAX
2463 } 2463 }
2464 } 2464 }
2465 2465
2466 TEST(ARMv8_vminmax_f32) { 2466 TEST(ARMv8_vminmax_f32) {
2467 // Test the vsel floating point instructions. 2467 // Test the vminnm and vmaxnm floating point instructions.
2468 CcTest::InitializeVM(); 2468 CcTest::InitializeVM();
2469 Isolate* isolate = CcTest::i_isolate(); 2469 Isolate* isolate = CcTest::i_isolate();
2470 HandleScope scope(isolate); 2470 HandleScope scope(isolate);
2471 2471
2472 Assembler assm(isolate, NULL, 0); 2472 Assembler assm(isolate, NULL, 0);
2473 2473
2474 struct Inputs { 2474 struct Inputs {
2475 float left_; 2475 float left_;
2476 float right_; 2476 float right_;
2477 }; 2477 };
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2538 2538
2539 CHECK_VMINMAX(0.0f, nan_a, 0.0f, 0.0f); 2539 CHECK_VMINMAX(0.0f, nan_a, 0.0f, 0.0f);
2540 CHECK_VMINMAX(nan_a, 0.0f, 0.0f, 0.0f); 2540 CHECK_VMINMAX(nan_a, 0.0f, 0.0f, 0.0f);
2541 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); 2541 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a);
2542 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); 2542 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b);
2543 2543
2544 #undef CHECK_VMINMAX 2544 #undef CHECK_VMINMAX
2545 } 2545 }
2546 } 2546 }
2547 2547
2548 template <typename T, typename Inputs, typename Results>
2549 static F4 GenerateMacroFloatMinMax(MacroAssembler& assm) {
2550 T a = T::from_code(0); // d0/s0
2551 T b = T::from_code(1); // d1/s1
2552 T c = T::from_code(2); // d2/s2
2553
2554 // Create a helper function:
2555 // void TestFloatMinMax(const Inputs* inputs,
2556 // Results* results);
2557 Label ool_min_abc, ool_min_aab, ool_min_aba;
2558 Label ool_max_abc, ool_max_aab, ool_max_aba;
2559
2560 Label done_min_abc, done_min_aab, done_min_aba;
2561 Label done_max_abc, done_max_aab, done_max_aba;
2562
2563 // a = min(b, c);
2564 __ vldr(b, r0, offsetof(Inputs, left_));
2565 __ vldr(c, r0, offsetof(Inputs, right_));
2566 __ FloatMin(a, b, c, &ool_min_abc);
2567 __ bind(&done_min_abc);
2568 __ vstr(a, r1, offsetof(Results, min_abc_));
2569
2570 // a = min(a, b);
2571 __ vldr(a, r0, offsetof(Inputs, left_));
2572 __ vldr(b, r0, offsetof(Inputs, right_));
2573 __ FloatMin(a, a, b, &ool_min_aab);
2574 __ bind(&done_min_aab);
2575 __ vstr(a, r1, offsetof(Results, min_aab_));
2576
2577 // a = min(b, a);
2578 __ vldr(b, r0, offsetof(Inputs, left_));
2579 __ vldr(a, r0, offsetof(Inputs, right_));
2580 __ FloatMin(a, b, a, &ool_min_aba);
2581 __ bind(&done_min_aba);
2582 __ vstr(a, r1, offsetof(Results, min_aba_));
2583
2584 // a = max(b, c);
2585 __ vldr(b, r0, offsetof(Inputs, left_));
2586 __ vldr(c, r0, offsetof(Inputs, right_));
2587 __ FloatMax(a, b, c, &ool_max_abc);
2588 __ bind(&done_max_abc);
2589 __ vstr(a, r1, offsetof(Results, max_abc_));
2590
2591 // a = max(a, b);
2592 __ vldr(a, r0, offsetof(Inputs, left_));
2593 __ vldr(b, r0, offsetof(Inputs, right_));
2594 __ FloatMax(a, a, b, &ool_max_aab);
2595 __ bind(&done_max_aab);
2596 __ vstr(a, r1, offsetof(Results, max_aab_));
2597
2598 // a = max(b, a);
2599 __ vldr(b, r0, offsetof(Inputs, left_));
2600 __ vldr(a, r0, offsetof(Inputs, right_));
2601 __ FloatMax(a, b, a, &ool_max_aba);
2602 __ bind(&done_max_aba);
2603 __ vstr(a, r1, offsetof(Results, max_aba_));
2604
2605 __ bx(lr);
2606
2607 // Generate out-of-line cases.
2608 __ bind(&ool_min_abc);
2609 __ FloatMinOutOfLine(a, b, c);
2610 __ b(&done_min_abc);
2611
2612 __ bind(&ool_min_aab);
2613 __ FloatMinOutOfLine(a, a, b);
2614 __ b(&done_min_aab);
2615
2616 __ bind(&ool_min_aba);
2617 __ FloatMinOutOfLine(a, b, a);
2618 __ b(&done_min_aba);
2619
2620 __ bind(&ool_max_abc);
2621 __ FloatMaxOutOfLine(a, b, c);
2622 __ b(&done_max_abc);
2623
2624 __ bind(&ool_max_aab);
2625 __ FloatMaxOutOfLine(a, a, b);
2626 __ b(&done_max_aab);
2627
2628 __ bind(&ool_max_aba);
2629 __ FloatMaxOutOfLine(a, b, a);
2630 __ b(&done_max_aba);
2631
2632 CodeDesc desc;
2633 assm.GetCode(&desc);
2634 Handle<Code> code = assm.isolate()->factory()->NewCode(
2635 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2636 #ifdef DEBUG
2637 OFStream os(stdout);
2638 code->Print(os);
2639 #endif
2640 return FUNCTION_CAST<F4>(code->entry());
2641 }
2642
2643 TEST(macro_float_minmax_f64) {
2644 // Test the FloatMin and FloatMax macros.
2645 CcTest::InitializeVM();
2646 Isolate* isolate = CcTest::i_isolate();
2647 HandleScope scope(isolate);
2648
2649 MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes);
2650
2651 struct Inputs {
2652 double left_;
2653 double right_;
2654 };
2655
2656 struct Results {
2657 // Check all register aliasing possibilities in order to exercise all
2658 // code-paths in the macro assembler.
2659 double min_abc_;
2660 double min_aab_;
2661 double min_aba_;
2662 double max_abc_;
2663 double max_aab_;
2664 double max_aba_;
2665 };
2666
2667 F4 f = GenerateMacroFloatMinMax<DwVfpRegister, Inputs, Results>(assm);
2668
2669 Object* dummy = nullptr;
2670 USE(dummy);
2671
2672 #define CHECK_MINMAX(left, right, min, max) \
2673 do { \
2674 Inputs inputs = {left, right}; \
2675 Results results; \
2676 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \
2677 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \
2678 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \
2679 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \
2680 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \
2681 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \
2682 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \
2683 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \
2684 } while (0)
2685
2686 double nan_a = bit_cast<double>(UINT64_C(0x7ff8000000000001));
2687 double nan_b = bit_cast<double>(UINT64_C(0x7ff8000000000002));
2688
2689 CHECK_MINMAX(1.0, -1.0, -1.0, 1.0);
2690 CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0);
2691 CHECK_MINMAX(0.0, -1.0, -1.0, 0.0);
2692 CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0);
2693 CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0);
2694 CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0);
2695 CHECK_MINMAX(0.0, 1.0, 0.0, 1.0);
2696 CHECK_MINMAX(1.0, 0.0, 0.0, 1.0);
2697
2698 CHECK_MINMAX(0.0, 0.0, 0.0, 0.0);
2699 CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0);
2700 CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0);
2701 CHECK_MINMAX(0.0, -0.0, -0.0, 0.0);
2702
2703 CHECK_MINMAX(0.0, nan_a, nan_a, nan_a);
2704 CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a);
2705 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a);
2706 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b);
2707
2708 #undef CHECK_MINMAX
2709 }
2710
2711 TEST(macro_float_minmax_f32) {
2712 // Test the FloatMin and FloatMax macros.
2713 CcTest::InitializeVM();
2714 Isolate* isolate = CcTest::i_isolate();
2715 HandleScope scope(isolate);
2716
2717 MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes);
2718
2719 struct Inputs {
2720 float left_;
2721 float right_;
2722 };
2723
2724 struct Results {
2725 // Check all register aliasing possibilities in order to exercise all
2726 // code-paths in the macro assembler.
2727 float min_abc_;
2728 float min_aab_;
2729 float min_aba_;
2730 float max_abc_;
2731 float max_aab_;
2732 float max_aba_;
2733 };
2734
2735 F4 f = GenerateMacroFloatMinMax<SwVfpRegister, Inputs, Results>(assm);
2736 Object* dummy = nullptr;
2737 USE(dummy);
2738
2739 #define CHECK_MINMAX(left, right, min, max) \
2740 do { \
2741 Inputs inputs = {left, right}; \
2742 Results results; \
2743 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \
2744 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \
2745 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \
2746 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \
2747 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \
2748 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \
2749 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \
2750 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \
2751 } while (0)
2752
2753 float nan_a = bit_cast<float>(UINT32_C(0x7fc00001));
2754 float nan_b = bit_cast<float>(UINT32_C(0x7fc00002));
2755
2756 CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f);
2757 CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f);
2758 CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f);
2759 CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f);
2760 CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f);
2761 CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f);
2762 CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f);
2763 CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f);
2764
2765 CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f);
2766 CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f);
2767 CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f);
2768 CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f);
2769
2770 CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a);
2771 CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a);
2772 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a);
2773 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b);
2774
2775 #undef CHECK_MINMAX
2776 }
2777
2548 TEST(unaligned_loads) { 2778 TEST(unaligned_loads) {
2549 // All supported ARM targets allow unaligned accesses. 2779 // All supported ARM targets allow unaligned accesses.
2550 CcTest::InitializeVM(); 2780 CcTest::InitializeVM();
2551 Isolate* isolate = CcTest::i_isolate(); 2781 Isolate* isolate = CcTest::i_isolate();
2552 HandleScope scope(isolate); 2782 HandleScope scope(isolate);
2553 2783
2554 typedef struct { 2784 typedef struct {
2555 uint32_t ldrh; 2785 uint32_t ldrh;
2556 uint32_t ldrsh; 2786 uint32_t ldrsh;
2557 uint32_t ldr; 2787 uint32_t ldr;
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2710 HandleScope scope(isolate); 2940 HandleScope scope(isolate);
2711 2941
2712 Assembler assm(isolate, NULL, 0); 2942 Assembler assm(isolate, NULL, 0);
2713 __ mov(r0, Operand(isolate->factory()->infinity_value())); 2943 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2714 __ BlockConstPoolFor(1019); 2944 __ BlockConstPoolFor(1019);
2715 for (int i = 0; i < 1019; ++i) __ nop(); 2945 for (int i = 0; i < 1019; ++i) __ nop();
2716 __ vldr(d0, MemOperand(r0, 0)); 2946 __ vldr(d0, MemOperand(r0, 0));
2717 } 2947 }
2718 2948
2719 #undef __ 2949 #undef __
OLDNEW
« no previous file with comments | « src/compiler/arm/code-generator-arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698