rv64: Skip zero chunks in wide immediates

9a9ad0762d09613b4059c17feee15b235ee0741eb40ad12e1c9e52a91034a3a8
Emit an ADDI for each low-bit chunk only when the chunk is nonzero.
Keep all shifts and signed upper-half loading so full-width values
remain correct while sparse constants need fewer target instructions.

Assisted-by: Codex:gpt-6-astra
Alexis Sellier committed ago 1 parent 587e7cb3
lib/std/arch/rv64/emit.rad +12 -3
524 524
525 525
    // Load upper 32 bits.
526 526
    loadImm(e, rd, hi32 as i64);
527 527
    // Shift left by 11, add bits [31:21].
528 528
    emit(e, encode::slli(rd, rd, 11));
529 -
    emit(e, encode::addi(rd, rd, (lower >> 21) & 0x7FF));
529 +
    let chunkHi = (lower >> 21) & 0x7FF;
530 +
    if chunkHi <> 0 {
531 +
        emit(e, encode::addi(rd, rd, chunkHi));
532 +
    }
530 533
    // Shift left by 11, add bits [20:10].
531 534
    emit(e, encode::slli(rd, rd, 11));
532 -
    emit(e, encode::addi(rd, rd, (lower >> 10) & 0x7FF));
535 +
    let chunkMid = (lower >> 10) & 0x7FF;
536 +
    if chunkMid <> 0 {
537 +
        emit(e, encode::addi(rd, rd, chunkMid));
538 +
    }
533 539
    // Shift left by 10, add bits [9:0].
534 540
    emit(e, encode::slli(rd, rd, 10));
535 -
    emit(e, encode::addi(rd, rd, lower & 0x3FF));
541 +
    let chunkLo = lower & 0x3FF;
542 +
    if chunkLo <> 0 {
543 +
        emit(e, encode::addi(rd, rd, chunkLo));
544 +
    }
536 545
}
537 546
538 547
/// Emit add-immediate, handling large immediates.
539 548
export fn emitAddImm(e: *mut Emitter, rd: gen::Reg, rs: gen::Reg, imm: i32) {
540 549
    if imm >= super::MIN_IMM and imm <= super::MAX_IMM {