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
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 { |