Use zero register directly for branch comparisons
3d0bcffc665968ce313e823343c2518980728ac940c42e905f98ebdd20d56df7
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 | } |