Use zero register directly for branch comparisons

3d0bcffc665968ce313e823343c2518980728ac940c42e905f98ebdd20d56df7
Alexis Sellier committed ago 1 parent a80ed464
lib/std/arch/rv64/isel.rad +19 -6
527 527
            if target != blockIdx + 1 {
528 528
                emit::recordBranch(s.e, target, emit::BranchKind::Jump);
529 529
            }
530 530
        },
531 531
        case il::Instr::Br { op, typ, a, b, thenTarget, thenArgs, elseTarget, elseArgs } => {
532 -
            let rs1 = resolveVal(s, super::SCRATCH1, a);
533 -
            let rs2 = resolveVal(s, super::SCRATCH2, b);
532 +
            // Use zero register directly for immediate `0` operands.
533 +
            let aIsZero = isZeroImm(a);
534 +
            let bIsZero = isZeroImm(b);
535 +
536 +
            let rs1 = super::ZERO if aIsZero else resolveVal(s, super::SCRATCH1, a);
537 +
            let rs2 = super::ZERO if bIsZero else resolveVal(s, super::SCRATCH2, b);
534 538
535 539
            // Normalize sub-word operands so that both registers have the same
536 540
            // canonical representation. Without this, eg. `-1 : i8 ` loaded as
537 541
            // `0xFFFFFFFFFFFFFFFF` and `255 : i8` loaded as `0xFF` would compare
538 542
            // unequal even though they are the same 8-bit pattern.
543 +
            // Skip extension for zero register.
539 544
            if let case il::CmpOp::Slt = op {
540 -
                emitSext(s.e, rs1, rs1, typ);
541 -
                emitSext(s.e, rs2, rs2, typ);
545 +
                if not aIsZero { emitSext(s.e, rs1, rs1, typ); }
546 +
                if not bIsZero { emitSext(s.e, rs2, rs2, typ); }
542 547
            } else {
543 -
                emitZext(s.e, rs1, rs1, typ);
544 -
                emitZext(s.e, rs2, rs2, typ);
548 +
                if not aIsZero { emitZext(s.e, rs1, rs1, typ); }
549 +
                if not bIsZero { emitZext(s.e, rs2, rs2, typ); }
545 550
            }
546 551
            // Block-argument moves must only execute on the taken path.
547 552
            // When `thenArgs` is non-empty, invert the branch so that the
548 553
            // then-moves land on the fall-through (taken) side.
549 554
            //
652 657
            emit::emit(s.e, encode::ebreak());
653 658
        },
654 659
    }
655 660
}
656 661
662 +
/// Check if a value is an immediate zero.
663 +
fn isZeroImm(val: il::Val) -> bool {
664 +
    if let case il::Val::Imm(imm) = val {
665 +
        return imm == 0;
666 +
    }
667 +
    return false;
668 +
}
669 +
657 670
/// Check if a value is a known non-zero immediate.
658 671
fn isNonZeroImm(val: il::Val) -> bool {
659 672
    if let case il::Val::Imm(imm) = val {
660 673
        return imm != 0;
661 674
    }