Skip division-by-zero check when possible

a80ed4644cbe3423a0bf1116ebad644a96541306de0704b35bbf9598734b8921
Alexis Sellier committed ago 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
        }