|
2499 | 2499 | )
|
2500 | 2500 | )
|
2501 | 2501 |
|
| 2502 | +(module |
| 2503 | + ;; Same as above but now the fields are mutable. |
| 2504 | + (rec |
| 2505 | + ;; CHECK: (rec |
| 2506 | + ;; CHECK-NEXT: (type $A (sub (struct (field (mut i32))))) |
| 2507 | + (type $A (sub (struct (field (mut i32))))) |
| 2508 | + ;; CHECK: (type $B (sub $A (struct (field (mut i32))))) |
| 2509 | + (type $B (sub $A (struct (field (mut i32))))) |
| 2510 | + ) |
| 2511 | + |
| 2512 | + ;; CHECK: (type $2 (func (param i32))) |
| 2513 | + |
| 2514 | + ;; CHECK: (func $test (type $2) (param $0 i32) |
| 2515 | + ;; CHECK-NEXT: (local $A (ref $A)) |
| 2516 | + ;; CHECK-NEXT: (local $B (ref $B)) |
| 2517 | + ;; CHECK-NEXT: (local $A-exact (ref (exact $A))) |
| 2518 | + ;; CHECK-NEXT: (local $B-exact (ref (exact $B))) |
| 2519 | + ;; CHECK-NEXT: (local.set $A |
| 2520 | + ;; CHECK-NEXT: (local.tee $A-exact |
| 2521 | + ;; CHECK-NEXT: (struct.new $A |
| 2522 | + ;; CHECK-NEXT: (i32.const 10) |
| 2523 | + ;; CHECK-NEXT: ) |
| 2524 | + ;; CHECK-NEXT: ) |
| 2525 | + ;; CHECK-NEXT: ) |
| 2526 | + ;; CHECK-NEXT: (local.set $B |
| 2527 | + ;; CHECK-NEXT: (local.tee $B-exact |
| 2528 | + ;; CHECK-NEXT: (struct.new $B |
| 2529 | + ;; CHECK-NEXT: (i32.const 20) |
| 2530 | + ;; CHECK-NEXT: ) |
| 2531 | + ;; CHECK-NEXT: ) |
| 2532 | + ;; CHECK-NEXT: ) |
| 2533 | + ;; CHECK-NEXT: (drop |
| 2534 | + ;; CHECK-NEXT: (struct.get $A 0 |
| 2535 | + ;; CHECK-NEXT: (local.get $A) |
| 2536 | + ;; CHECK-NEXT: ) |
| 2537 | + ;; CHECK-NEXT: ) |
| 2538 | + ;; CHECK-NEXT: (drop |
| 2539 | + ;; CHECK-NEXT: (block (result i32) |
| 2540 | + ;; CHECK-NEXT: (drop |
| 2541 | + ;; CHECK-NEXT: (ref.as_non_null |
| 2542 | + ;; CHECK-NEXT: (local.get $B) |
| 2543 | + ;; CHECK-NEXT: ) |
| 2544 | + ;; CHECK-NEXT: ) |
| 2545 | + ;; CHECK-NEXT: (i32.const 20) |
| 2546 | + ;; CHECK-NEXT: ) |
| 2547 | + ;; CHECK-NEXT: ) |
| 2548 | + ;; CHECK-NEXT: (drop |
| 2549 | + ;; CHECK-NEXT: (struct.get $A 0 |
| 2550 | + ;; CHECK-NEXT: (local.get $A-exact) |
| 2551 | + ;; CHECK-NEXT: ) |
| 2552 | + ;; CHECK-NEXT: ) |
| 2553 | + ;; CHECK-NEXT: (drop |
| 2554 | + ;; CHECK-NEXT: (block (result i32) |
| 2555 | + ;; CHECK-NEXT: (drop |
| 2556 | + ;; CHECK-NEXT: (ref.as_non_null |
| 2557 | + ;; CHECK-NEXT: (local.get $B-exact) |
| 2558 | + ;; CHECK-NEXT: ) |
| 2559 | + ;; CHECK-NEXT: ) |
| 2560 | + ;; CHECK-NEXT: (i32.const 20) |
| 2561 | + ;; CHECK-NEXT: ) |
| 2562 | + ;; CHECK-NEXT: ) |
| 2563 | + ;; CHECK-NEXT: ) |
| 2564 | + (func $test (param $0 i32) |
| 2565 | + (local $A (ref $A)) |
| 2566 | + (local $B (ref $B)) |
| 2567 | + (local $A-exact (ref (exact $A))) |
| 2568 | + (local $B-exact (ref (exact $B))) |
| 2569 | + (local.set $A |
| 2570 | + (local.tee $A-exact |
| 2571 | + (struct.new $A |
| 2572 | + (i32.const 10) |
| 2573 | + ) |
| 2574 | + ) |
| 2575 | + ) |
| 2576 | + (local.set $B |
| 2577 | + (local.tee $B-exact |
| 2578 | + (struct.new $B |
| 2579 | + (i32.const 20) |
| 2580 | + ) |
| 2581 | + ) |
| 2582 | + ) |
| 2583 | + ;; We can optimize an inexact $B, but not $A. |
| 2584 | + (drop |
| 2585 | + (struct.get $A 0 |
| 2586 | + (local.get $A) |
| 2587 | + ) |
| 2588 | + ) |
| 2589 | + (drop |
| 2590 | + (struct.get $B 0 |
| 2591 | + (local.get $B) |
| 2592 | + ) |
| 2593 | + ) |
| 2594 | + ;; We should be able to optimize both exact references TODO. |
| 2595 | + (drop |
| 2596 | + (struct.get $A 0 |
| 2597 | + (local.get $A-exact) |
| 2598 | + ) |
| 2599 | + ) |
| 2600 | + (drop |
| 2601 | + (struct.get $B 0 |
| 2602 | + (local.get $B-exact) |
| 2603 | + ) |
| 2604 | + ) |
| 2605 | + ) |
| 2606 | +) |
| 2607 | + |
| 2608 | +(module |
| 2609 | + ;; Same as above but now we add no-op sets. |
| 2610 | + (rec |
| 2611 | + ;; CHECK: (rec |
| 2612 | + ;; CHECK-NEXT: (type $A (sub (struct (field (mut i32))))) |
| 2613 | + (type $A (sub (struct (field (mut i32))))) |
| 2614 | + ;; CHECK: (type $B (sub $A (struct (field (mut i32))))) |
| 2615 | + (type $B (sub $A (struct (field (mut i32))))) |
| 2616 | + ) |
| 2617 | + |
| 2618 | + ;; CHECK: (type $2 (func (param i32))) |
| 2619 | + |
| 2620 | + ;; CHECK: (func $test (type $2) (param $0 i32) |
| 2621 | + ;; CHECK-NEXT: (local $A (ref $A)) |
| 2622 | + ;; CHECK-NEXT: (local $B (ref $B)) |
| 2623 | + ;; CHECK-NEXT: (local $A-exact (ref (exact $A))) |
| 2624 | + ;; CHECK-NEXT: (local $B-exact (ref (exact $B))) |
| 2625 | + ;; CHECK-NEXT: (local.set $A |
| 2626 | + ;; CHECK-NEXT: (local.tee $A-exact |
| 2627 | + ;; CHECK-NEXT: (struct.new $A |
| 2628 | + ;; CHECK-NEXT: (i32.const 10) |
| 2629 | + ;; CHECK-NEXT: ) |
| 2630 | + ;; CHECK-NEXT: ) |
| 2631 | + ;; CHECK-NEXT: ) |
| 2632 | + ;; CHECK-NEXT: (local.set $B |
| 2633 | + ;; CHECK-NEXT: (local.tee $B-exact |
| 2634 | + ;; CHECK-NEXT: (struct.new $B |
| 2635 | + ;; CHECK-NEXT: (i32.const 20) |
| 2636 | + ;; CHECK-NEXT: ) |
| 2637 | + ;; CHECK-NEXT: ) |
| 2638 | + ;; CHECK-NEXT: ) |
| 2639 | + ;; CHECK-NEXT: (struct.set $A 0 |
| 2640 | + ;; CHECK-NEXT: (local.get $A-exact) |
| 2641 | + ;; CHECK-NEXT: (i32.const 10) |
| 2642 | + ;; CHECK-NEXT: ) |
| 2643 | + ;; CHECK-NEXT: (struct.set $B 0 |
| 2644 | + ;; CHECK-NEXT: (local.get $B-exact) |
| 2645 | + ;; CHECK-NEXT: (i32.const 20) |
| 2646 | + ;; CHECK-NEXT: ) |
| 2647 | + ;; CHECK-NEXT: (drop |
| 2648 | + ;; CHECK-NEXT: (struct.get $A 0 |
| 2649 | + ;; CHECK-NEXT: (local.get $A) |
| 2650 | + ;; CHECK-NEXT: ) |
| 2651 | + ;; CHECK-NEXT: ) |
| 2652 | + ;; CHECK-NEXT: (drop |
| 2653 | + ;; CHECK-NEXT: (struct.get $B 0 |
| 2654 | + ;; CHECK-NEXT: (local.get $B) |
| 2655 | + ;; CHECK-NEXT: ) |
| 2656 | + ;; CHECK-NEXT: ) |
| 2657 | + ;; CHECK-NEXT: (drop |
| 2658 | + ;; CHECK-NEXT: (struct.get $A 0 |
| 2659 | + ;; CHECK-NEXT: (local.get $A-exact) |
| 2660 | + ;; CHECK-NEXT: ) |
| 2661 | + ;; CHECK-NEXT: ) |
| 2662 | + ;; CHECK-NEXT: (drop |
| 2663 | + ;; CHECK-NEXT: (struct.get $B 0 |
| 2664 | + ;; CHECK-NEXT: (local.get $B-exact) |
| 2665 | + ;; CHECK-NEXT: ) |
| 2666 | + ;; CHECK-NEXT: ) |
| 2667 | + ;; CHECK-NEXT: ) |
| 2668 | + (func $test (param $0 i32) |
| 2669 | + (local $A (ref $A)) |
| 2670 | + (local $B (ref $B)) |
| 2671 | + (local $A-exact (ref (exact $A))) |
| 2672 | + (local $B-exact (ref (exact $B))) |
| 2673 | + (local.set $A |
| 2674 | + (local.tee $A-exact |
| 2675 | + (struct.new $A |
| 2676 | + (i32.const 10) |
| 2677 | + ) |
| 2678 | + ) |
| 2679 | + ) |
| 2680 | + (local.set $B |
| 2681 | + (local.tee $B-exact |
| 2682 | + (struct.new $B |
| 2683 | + (i32.const 20) |
| 2684 | + ) |
| 2685 | + ) |
| 2686 | + ) |
| 2687 | + ;; No-op exact sets should not inhibit optimization. |
| 2688 | + (struct.set $A 0 |
| 2689 | + (local.get $A-exact) |
| 2690 | + (i32.const 10) |
| 2691 | + ) |
| 2692 | + (struct.set $B 0 |
| 2693 | + (local.get $B-exact) |
| 2694 | + (i32.const 20) |
| 2695 | + ) |
| 2696 | + ;; We should be able to optimize an inexact $B, but not $A TODO. |
| 2697 | + (drop |
| 2698 | + (struct.get $A 0 |
| 2699 | + (local.get $A) |
| 2700 | + ) |
| 2701 | + ) |
| 2702 | + (drop |
| 2703 | + (struct.get $B 0 |
| 2704 | + (local.get $B) |
| 2705 | + ) |
| 2706 | + ) |
| 2707 | + ;; We should be able to optimize both exact references TODO. |
| 2708 | + (drop |
| 2709 | + (struct.get $A 0 |
| 2710 | + (local.get $A-exact) |
| 2711 | + ) |
| 2712 | + ) |
| 2713 | + (drop |
| 2714 | + (struct.get $B 0 |
| 2715 | + (local.get $B-exact) |
| 2716 | + ) |
| 2717 | + ) |
| 2718 | + ) |
| 2719 | +) |
| 2720 | + |
| 2721 | +(module |
| 2722 | + ;; Sets to a subtype should not affect exact gets of a supertype or sibling. |
| 2723 | + (rec |
| 2724 | + ;; CHECK: (rec |
| 2725 | + ;; CHECK-NEXT: (type $A (sub (struct (field (mut i32))))) |
| 2726 | + (type $A (sub (struct (field (mut i32))))) |
| 2727 | + ;; CHECK: (type $B (sub $A (struct (field (mut i32))))) |
| 2728 | + (type $B (sub $A (struct (field (mut i32))))) |
| 2729 | + ;; CHECK: (type $C (sub $A (struct (field (mut i32))))) |
| 2730 | + (type $C (sub $A (struct (field (mut i32))))) |
| 2731 | + ) |
| 2732 | + |
| 2733 | + ;; CHECK: (type $3 (func)) |
| 2734 | + |
| 2735 | + ;; CHECK: (type $4 (func (param (ref $B)))) |
| 2736 | + |
| 2737 | + ;; CHECK: (type $5 (func (param (ref $A) (ref $B) (ref $C)))) |
| 2738 | + |
| 2739 | + ;; CHECK: (type $6 (func (param (ref (exact $A)) (ref (exact $B)) (ref (exact $C))))) |
| 2740 | + |
| 2741 | + ;; CHECK: (func $news (type $3) |
| 2742 | + ;; CHECK-NEXT: (drop |
| 2743 | + ;; CHECK-NEXT: (struct.new $A |
| 2744 | + ;; CHECK-NEXT: (i32.const 10) |
| 2745 | + ;; CHECK-NEXT: ) |
| 2746 | + ;; CHECK-NEXT: ) |
| 2747 | + ;; CHECK-NEXT: (drop |
| 2748 | + ;; CHECK-NEXT: (struct.new $B |
| 2749 | + ;; CHECK-NEXT: (i32.const 20) |
| 2750 | + ;; CHECK-NEXT: ) |
| 2751 | + ;; CHECK-NEXT: ) |
| 2752 | + ;; CHECK-NEXT: (drop |
| 2753 | + ;; CHECK-NEXT: (struct.new $C |
| 2754 | + ;; CHECK-NEXT: (i32.const 30) |
| 2755 | + ;; CHECK-NEXT: ) |
| 2756 | + ;; CHECK-NEXT: ) |
| 2757 | + ;; CHECK-NEXT: ) |
| 2758 | + (func $news |
| 2759 | + (drop |
| 2760 | + (struct.new $A |
| 2761 | + (i32.const 10) |
| 2762 | + ) |
| 2763 | + ) |
| 2764 | + (drop |
| 2765 | + (struct.new $B |
| 2766 | + (i32.const 20) |
| 2767 | + ) |
| 2768 | + ) |
| 2769 | + (drop |
| 2770 | + (struct.new $C |
| 2771 | + (i32.const 30) |
| 2772 | + ) |
| 2773 | + ) |
| 2774 | + ) |
| 2775 | + |
| 2776 | + ;; CHECK: (func $set-B (type $4) (param $B (ref $B)) |
| 2777 | + ;; CHECK-NEXT: (struct.set $B 0 |
| 2778 | + ;; CHECK-NEXT: (local.get $B) |
| 2779 | + ;; CHECK-NEXT: (i32.const 666) |
| 2780 | + ;; CHECK-NEXT: ) |
| 2781 | + ;; CHECK-NEXT: ) |
| 2782 | + (func $set-B (param $B (ref $B)) |
| 2783 | + ;; Inhibits optimizations on B and inexact A only. |
| 2784 | + (struct.set $B 0 |
| 2785 | + (local.get $B) |
| 2786 | + (i32.const 666) |
| 2787 | + ) |
| 2788 | + ) |
| 2789 | + |
| 2790 | + ;; CHECK: (func $inexact-gets (type $5) (param $A (ref $A)) (param $B (ref $B)) (param $C (ref $C)) |
| 2791 | + ;; CHECK-NEXT: (drop |
| 2792 | + ;; CHECK-NEXT: (struct.get $A 0 |
| 2793 | + ;; CHECK-NEXT: (local.get $A) |
| 2794 | + ;; CHECK-NEXT: ) |
| 2795 | + ;; CHECK-NEXT: ) |
| 2796 | + ;; CHECK-NEXT: (drop |
| 2797 | + ;; CHECK-NEXT: (struct.get $B 0 |
| 2798 | + ;; CHECK-NEXT: (local.get $B) |
| 2799 | + ;; CHECK-NEXT: ) |
| 2800 | + ;; CHECK-NEXT: ) |
| 2801 | + ;; CHECK-NEXT: (drop |
| 2802 | + ;; CHECK-NEXT: (struct.get $C 0 |
| 2803 | + ;; CHECK-NEXT: (local.get $C) |
| 2804 | + ;; CHECK-NEXT: ) |
| 2805 | + ;; CHECK-NEXT: ) |
| 2806 | + ;; CHECK-NEXT: ) |
| 2807 | + (func $inexact-gets (param $A (ref $A)) (param $B (ref $B)) (param $C (ref $C)) |
| 2808 | + (drop |
| 2809 | + (struct.get $A 0 |
| 2810 | + (local.get $A) |
| 2811 | + ) |
| 2812 | + ) |
| 2813 | + (drop |
| 2814 | + (struct.get $B 0 |
| 2815 | + (local.get $B) |
| 2816 | + ) |
| 2817 | + ) |
| 2818 | + ;; This should be optimizable TODO. |
| 2819 | + (drop |
| 2820 | + (struct.get $C 0 |
| 2821 | + (local.get $C) |
| 2822 | + ) |
| 2823 | + ) |
| 2824 | + ) |
| 2825 | + |
| 2826 | + ;; CHECK: (func $exact-gets (type $6) (param $A-exact (ref (exact $A))) (param $B-exact (ref (exact $B))) (param $C-exact (ref (exact $C))) |
| 2827 | + ;; CHECK-NEXT: (drop |
| 2828 | + ;; CHECK-NEXT: (struct.get $A 0 |
| 2829 | + ;; CHECK-NEXT: (local.get $A-exact) |
| 2830 | + ;; CHECK-NEXT: ) |
| 2831 | + ;; CHECK-NEXT: ) |
| 2832 | + ;; CHECK-NEXT: (drop |
| 2833 | + ;; CHECK-NEXT: (struct.get $B 0 |
| 2834 | + ;; CHECK-NEXT: (local.get $B-exact) |
| 2835 | + ;; CHECK-NEXT: ) |
| 2836 | + ;; CHECK-NEXT: ) |
| 2837 | + ;; CHECK-NEXT: (drop |
| 2838 | + ;; CHECK-NEXT: (struct.get $C 0 |
| 2839 | + ;; CHECK-NEXT: (local.get $C-exact) |
| 2840 | + ;; CHECK-NEXT: ) |
| 2841 | + ;; CHECK-NEXT: ) |
| 2842 | + ;; CHECK-NEXT: ) |
| 2843 | + (func $exact-gets (param $A-exact (ref (exact $A))) |
| 2844 | + (param $B-exact (ref (exact $B))) |
| 2845 | + (param $C-exact (ref (exact $C))) |
| 2846 | + (drop |
| 2847 | + ;; This should be optimizable TODO. |
| 2848 | + (struct.get $A 0 |
| 2849 | + (local.get $A-exact) |
| 2850 | + ) |
| 2851 | + ) |
| 2852 | + ;; Not optimizable. |
| 2853 | + (drop |
| 2854 | + (struct.get $B 0 |
| 2855 | + (local.get $B-exact) |
| 2856 | + ) |
| 2857 | + ) |
| 2858 | + ;; This should be optimizable TODO. |
| 2859 | + (drop |
| 2860 | + (struct.get $C 0 |
| 2861 | + (local.get $C-exact) |
| 2862 | + ) |
| 2863 | + ) |
| 2864 | + ) |
| 2865 | +) |
| 2866 | + |
2502 | 2867 | ;; A type with two subtypes. A copy on the parent can affect either child.
|
2503 | 2868 | (module
|
2504 | 2869 | (rec
|
|
0 commit comments