Skip division-by-zero check when possible
a80ed4644cbe3423a0bf1116ebad644a96541306de0704b35bbf9598734b8921
1 parent
a81e1717
lib/std/arch/rv64/isel.rad
+20 -4
| 652 | 652 | emit::emit(s.e, encode::ebreak()); |
|
| 653 | 653 | }, |
|
| 654 | 654 | } |
|
| 655 | 655 | } |
|
| 656 | 656 | ||
| 657 | + | /// Check if a value is a known non-zero immediate. |
|
| 658 | + | fn isNonZeroImm(val: il::Val) -> bool { |
|
| 659 | + | if let case il::Val::Imm(imm) = val { |
|
| 660 | + | return imm != 0; |
|
| 661 | + | } |
|
| 662 | + | return false; |
|
| 663 | + | } |
|
| 664 | + | ||
| 657 | 665 | /// Emit runtime trap for division/modulo by zero. |
|
| 658 | 666 | fn emitTrapIfZero(s: *mut Selector, rs: super::Reg) { |
|
| 659 | 667 | emit::emit(s.e, encode::bne(rs, super::ZERO, super::INSTR_SIZE * 2)); |
|
| 660 | 668 | emit::emit(s.e, encode::ebreak()); |
|
| 661 | 669 | } |
| 706 | 714 | encode::mul(rd, rs1, rs2)); |
|
| 707 | 715 | } |
|
| 708 | 716 | } |
|
| 709 | 717 | case il::BinOp::Sdiv => { |
|
| 710 | 718 | let rs2 = resolveVal(s, super::SCRATCH2, b); |
|
| 711 | - | emitTrapIfZero(s, rs2); |
|
| 719 | + | if not isNonZeroImm(b) { |
|
| 720 | + | emitTrapIfZero(s, rs2); |
|
| 721 | + | } |
|
| 712 | 722 | emit::emit(s.e, |
|
| 713 | 723 | encode::divw(rd, rs1, rs2) |
|
| 714 | 724 | if typ == il::Type::W32 else |
|
| 715 | 725 | encode::div(rd, rs1, rs2)); |
|
| 716 | 726 | } |
|
| 717 | 727 | case il::BinOp::Udiv => { |
|
| 718 | 728 | let rs2 = resolveVal(s, super::SCRATCH2, b); |
|
| 719 | - | emitTrapIfZero(s, rs2); |
|
| 729 | + | if not isNonZeroImm(b) { |
|
| 730 | + | emitTrapIfZero(s, rs2); |
|
| 731 | + | } |
|
| 720 | 732 | emit::emit(s.e, |
|
| 721 | 733 | encode::divuw(rd, rs1, rs2) |
|
| 722 | 734 | if typ == il::Type::W32 else |
|
| 723 | 735 | encode::divu(rd, rs1, rs2)); |
|
| 724 | 736 | } |
|
| 725 | 737 | case il::BinOp::Srem => { |
|
| 726 | 738 | let rs2 = resolveVal(s, super::SCRATCH2, b); |
|
| 727 | - | emitTrapIfZero(s, rs2); |
|
| 739 | + | if not isNonZeroImm(b) { |
|
| 740 | + | emitTrapIfZero(s, rs2); |
|
| 741 | + | } |
|
| 728 | 742 | emit::emit(s.e, |
|
| 729 | 743 | encode::remw(rd, rs1, rs2) |
|
| 730 | 744 | if typ == il::Type::W32 else |
|
| 731 | 745 | encode::rem(rd, rs1, rs2)); |
|
| 732 | 746 | } |
|
| 733 | 747 | case il::BinOp::Urem => { |
|
| 734 | 748 | let rs2 = resolveVal(s, super::SCRATCH2, b); |
|
| 735 | - | emitTrapIfZero(s, rs2); |
|
| 749 | + | if not isNonZeroImm(b) { |
|
| 750 | + | emitTrapIfZero(s, rs2); |
|
| 751 | + | } |
|
| 736 | 752 | emit::emit(s.e, |
|
| 737 | 753 | encode::remuw(rd, rs1, rs2) |
|
| 738 | 754 | if typ == il::Type::W32 else |
|
| 739 | 755 | encode::remu(rd, rs1, rs2)); |
|
| 740 | 756 | } |