|
4 | 4 | ;; register(s) within which the lowered instruction's result values live. |
5 | 5 | (decl lower (Inst) InstOutput) |
6 | 6 |
|
| 7 | +;; Variant of the main lowering constructor term, which receives an |
| 8 | +;; additional argument (a vector of branch targets to be used) for |
| 9 | +;; implementing branches. |
| 10 | +;; For two-branch instructions, the first target is `taken` and the second |
| 11 | +;; `not_taken`, even if it is a Fallthrough instruction: because we reorder |
| 12 | +;; blocks while we lower, the fallthrough in the new order is not (necessarily) |
| 13 | +;; the same as the fallthrough in CLIF. So, we use the explicitly-provided |
| 14 | +;; target. |
| 15 | +(decl lower_branch (Inst VecMachLabel) InstOutput) |
| 16 | + |
7 | 17 | ;;;; Rules for `iconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
8 | 18 |
|
9 | 19 | (rule (lower (has_type ty (iconst (u64_from_imm64 n)))) |
|
2497 | 2507 |
|
2498 | 2508 | ;;; Rules for `brz`/`brnz`/`brif`/`brff`/`bricmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2499 | 2509 |
|
2500 | | -;; TODO: requires icmp/fcmp first. |
| 2510 | +;; `brz` following `icmp`, possibly converted via `bint`. |
| 2511 | +(rule (lower_branch (brz (icmp cc x @ (value_type ty) y) _ _) targets) |
| 2512 | + (let ((cond Cond (cond_code cc)) |
| 2513 | + (cond Cond (invert_cond cond)) ;; negate for `brz` |
| 2514 | + (taken BranchTarget (branch_target targets 0)) |
| 2515 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2516 | + (side_effect |
| 2517 | + (with_flags_side_effect (lower_icmp_into_flags cc x y ty) |
| 2518 | + (cond_br taken not_taken |
| 2519 | + (cond_br_cond cond)))))) |
| 2520 | +(rule (lower_branch (brz (bint (icmp cc x @ (value_type ty) y)) _ _) targets) |
| 2521 | + (let ((cond Cond (cond_code cc)) |
| 2522 | + (cond Cond (invert_cond cond)) ;; negate for `brz` |
| 2523 | + (taken BranchTarget (branch_target targets 0)) |
| 2524 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2525 | + (side_effect |
| 2526 | + (with_flags_side_effect (lower_icmp_into_flags cc x y ty) |
| 2527 | + (cond_br taken not_taken |
| 2528 | + (cond_br_cond cond)))))) |
| 2529 | +;; `brnz` following `icmp`, possibly converted via `bint`. |
| 2530 | +(rule (lower_branch (brnz (icmp cc x @ (value_type ty) y) _ _) targets) |
| 2531 | + (let ((cond Cond (cond_code cc)) |
| 2532 | + (taken BranchTarget (branch_target targets 0)) |
| 2533 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2534 | + (side_effect |
| 2535 | + (with_flags_side_effect (lower_icmp_into_flags cc x y ty) |
| 2536 | + (cond_br taken not_taken |
| 2537 | + (cond_br_cond cond)))))) |
| 2538 | +(rule (lower_branch (brnz (bint (icmp cc x @ (value_type ty) y)) _ _) targets) |
| 2539 | + (let ((cond Cond (cond_code cc)) |
| 2540 | + (taken BranchTarget (branch_target targets 0)) |
| 2541 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2542 | + (side_effect |
| 2543 | + (with_flags_side_effect (lower_icmp_into_flags cc x y ty) |
| 2544 | + (cond_br taken not_taken |
| 2545 | + (cond_br_cond cond)))))) |
| 2546 | +;; `brz` following `fcmp`, possibly converted via `bint`. |
| 2547 | +(rule (lower_branch (brz (fcmp cc x @ (value_type (ty_scalar_float ty)) y) _ _) targets) |
| 2548 | + (let ((cond Cond (fp_cond_code cc)) |
| 2549 | + (cond Cond (invert_cond cond)) ;; negate for `brz` |
| 2550 | + (taken BranchTarget (branch_target targets 0)) |
| 2551 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2552 | + (side_effect |
| 2553 | + (with_flags_side_effect (fpu_cmp (scalar_size ty) x y) |
| 2554 | + (cond_br taken not_taken |
| 2555 | + (cond_br_cond cond)))))) |
| 2556 | +(rule (lower_branch (brz (bint (fcmp cc x @ (value_type (ty_scalar_float ty)) y)) _ _) targets) |
| 2557 | + (let ((cond Cond (fp_cond_code cc)) |
| 2558 | + (cond Cond (invert_cond cond)) ;; negate for `brz` |
| 2559 | + (taken BranchTarget (branch_target targets 0)) |
| 2560 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2561 | + (side_effect |
| 2562 | + (with_flags_side_effect (fpu_cmp (scalar_size ty) x y) |
| 2563 | + (cond_br taken not_taken |
| 2564 | + (cond_br_cond cond)))))) |
| 2565 | +;; `brnz` following `fcmp`, possibly converted via `bint`. |
| 2566 | +(rule (lower_branch (brnz (fcmp cc x @ (value_type (ty_scalar_float ty)) y) _ _) targets) |
| 2567 | + (let ((cond Cond (fp_cond_code cc)) |
| 2568 | + (taken BranchTarget (branch_target targets 0)) |
| 2569 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2570 | + (side_effect |
| 2571 | + (with_flags_side_effect (fpu_cmp (scalar_size ty) x y) |
| 2572 | + (cond_br taken not_taken |
| 2573 | + (cond_br_cond cond)))))) |
| 2574 | +(rule (lower_branch (brnz (bint (fcmp cc x @ (value_type (ty_scalar_float ty)) y)) _ _) targets) |
| 2575 | + (let ((cond Cond (fp_cond_code cc)) |
| 2576 | + (taken BranchTarget (branch_target targets 0)) |
| 2577 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2578 | + (side_effect |
| 2579 | + (with_flags_side_effect (fpu_cmp (scalar_size ty) x y) |
| 2580 | + (cond_br taken not_taken |
| 2581 | + (cond_br_cond cond)))))) |
| 2582 | +;; standard `brz` |
| 2583 | +(rule (lower_branch (brz c @ (value_type $I128) _ _) targets) |
| 2584 | + (let ((flags ProducesFlags (flags_to_producesflags c)) |
| 2585 | + (c ValueRegs (put_in_regs c)) |
| 2586 | + (c_lo Reg (value_regs_get c 0)) |
| 2587 | + (c_hi Reg (value_regs_get c 1)) |
| 2588 | + (rt Reg (orr $I64 c_lo c_hi)) |
| 2589 | + (taken BranchTarget (branch_target targets 0)) |
| 2590 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2591 | + (side_effect |
| 2592 | + (with_flags_side_effect flags |
| 2593 | + (cond_br taken not_taken (cond_br_zero rt)))))) |
| 2594 | +(rule (lower_branch (brz c @ (value_type ty) _ _) targets) |
| 2595 | + (if (ty_int_bool_ref_scalar_64 ty)) |
| 2596 | + (let ((flags ProducesFlags (flags_to_producesflags c)) |
| 2597 | + (rt Reg (put_in_reg_zext64 c)) |
| 2598 | + (taken BranchTarget (branch_target targets 0)) |
| 2599 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2600 | + (side_effect |
| 2601 | + (with_flags_side_effect flags |
| 2602 | + (cond_br taken not_taken (cond_br_zero rt)))))) |
| 2603 | +;; standard `brnz` |
| 2604 | +(rule (lower_branch (brnz c @ (value_type $I128) _ _) targets) |
| 2605 | + (let ((flags ProducesFlags (flags_to_producesflags c)) |
| 2606 | + (c ValueRegs (put_in_regs c)) |
| 2607 | + (c_lo Reg (value_regs_get c 0)) |
| 2608 | + (c_hi Reg (value_regs_get c 1)) |
| 2609 | + (rt Reg (orr $I64 c_lo c_hi)) |
| 2610 | + (taken BranchTarget (branch_target targets 0)) |
| 2611 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2612 | + (side_effect |
| 2613 | + (with_flags_side_effect flags |
| 2614 | + (cond_br taken not_taken (cond_br_not_zero rt)))))) |
| 2615 | +(rule (lower_branch (brnz c @ (value_type ty) _ _) targets) |
| 2616 | + (if (ty_int_bool_ref_scalar_64 ty)) |
| 2617 | + (let ((flags ProducesFlags (flags_to_producesflags c)) |
| 2618 | + (rt Reg (put_in_reg_zext64 c)) |
| 2619 | + (taken BranchTarget (branch_target targets 0)) |
| 2620 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2621 | + (side_effect |
| 2622 | + (with_flags_side_effect flags |
| 2623 | + (cond_br taken not_taken (cond_br_not_zero rt)))))) |
| 2624 | + |
| 2625 | +;; `br_icmp` |
| 2626 | +(rule (lower_branch (br_icmp cc x @ (value_type ty) y _ _) targets) |
| 2627 | + (let ((cond Cond (cond_code cc)) |
| 2628 | + (taken BranchTarget (branch_target targets 0)) |
| 2629 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2630 | + (side_effect |
| 2631 | + (with_flags_side_effect (lower_icmp_into_flags cc x y ty) |
| 2632 | + (cond_br taken not_taken |
| 2633 | + (cond_br_cond cond)))))) |
| 2634 | + |
| 2635 | +;; `brif` |
| 2636 | +(rule (lower_branch (brif cc (ifcmp x @ (value_type ty) y) _ _) targets) |
| 2637 | + (let ((cond Cond (cond_code cc)) |
| 2638 | + (taken BranchTarget (branch_target targets 0)) |
| 2639 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2640 | + (side_effect |
| 2641 | + (with_flags_side_effect (lower_icmp_into_flags cc x y ty) |
| 2642 | + (cond_br taken not_taken |
| 2643 | + (cond_br_cond cond)))))) |
| 2644 | +;; If the `ifcmp` result is actually placed in a register, we need to move it |
| 2645 | +;; back into the flags. |
| 2646 | +(rule -1 (lower_branch (brif cc f _ _) targets) |
| 2647 | + (let ((cond Cond (cond_code cc)) |
| 2648 | + (rn Reg (put_in_reg f)) |
| 2649 | + (taken BranchTarget (branch_target targets 0)) |
| 2650 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2651 | + (side_effect |
| 2652 | + (with_flags_side_effect (mov_to_nzcv rn) |
| 2653 | + (cond_br taken not_taken |
| 2654 | + (cond_br_cond cond)))))) |
| 2655 | + |
| 2656 | +;; `brff` |
| 2657 | +(rule (lower_branch (brff cc (ffcmp x @ (value_type ty) y) _ _) targets) |
| 2658 | + (let ((cond Cond (fp_cond_code cc)) |
| 2659 | + (taken BranchTarget (branch_target targets 0)) |
| 2660 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2661 | + (side_effect |
| 2662 | + (with_flags_side_effect (fpu_cmp (scalar_size ty) x y) |
| 2663 | + (cond_br taken not_taken |
| 2664 | + (cond_br_cond cond)))))) |
| 2665 | +;; If the `ffcmp` result is actually placed in a register, we need to move it |
| 2666 | +;; back into the flags. |
| 2667 | +(rule -1 (lower_branch (brff cc f _ _) targets) |
| 2668 | + (let ((cond Cond (fp_cond_code cc)) |
| 2669 | + (rn Reg (put_in_reg f)) |
| 2670 | + (taken BranchTarget (branch_target targets 0)) |
| 2671 | + (not_taken BranchTarget (branch_target targets 1))) |
| 2672 | + (side_effect |
| 2673 | + (with_flags_side_effect (mov_to_nzcv rn) |
| 2674 | + (cond_br taken not_taken |
| 2675 | + (cond_br_cond cond)))))) |
2501 | 2676 |
|
2502 | 2677 | ;;; Rules for `jump` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2503 | 2678 |
|
2504 | | -;; TODO. |
| 2679 | +(rule (lower_branch (jump _ _) targets) |
| 2680 | + (side_effect (aarch64_jump (branch_target targets 0)))) |
2505 | 2681 |
|
2506 | 2682 | ;;; Rules for `br_table` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2507 | 2683 |
|
2508 | | -;; TODO. |
| 2684 | +;; `targets` contains the default target with the list of branch targets |
| 2685 | +;; concatenated. |
| 2686 | +(rule (lower_branch (br_table idx _ _) targets) |
| 2687 | + (let ((jt_size u32 (targets_jt_size targets)) |
| 2688 | + (_ InstOutput (side_effect |
| 2689 | + (emit_island (targets_jt_space targets)))) |
| 2690 | + (ridx Reg (put_in_reg_zext32 idx))) |
| 2691 | + (br_table_impl (u32_as_u64 jt_size) ridx targets))) |
0 commit comments