Use sign-extension for all W32 branch comparisons
ce3e5c399d9462245c5936c3dbdace623df87de8f9bd94333b02fd575a7c6b49
1 parent
da5a5cd5
lib/std/arch/rv64/isel.rad
+8 -5
| 547 | 547 | // For SLT: sign-extension needed (signed comparison). |
|
| 548 | 548 | // For ULT: zero-extension needed (unsigned magnitude comparison). |
|
| 549 | 549 | // For EQ/NE with W32: sign-extension is cheaper. |
|
| 550 | 550 | // For EQ/NE with W8/W16: keep zero-extension. |
|
| 551 | 551 | // Skip extension for zero register. |
|
| 552 | - | if let case il::CmpOp::Slt = op { |
|
| 552 | + | if typ == il::Type::W32 { |
|
| 553 | + | // Sign-extension suffices for *all* comparison types on RV64. |
|
| 554 | + | // For SLT: sign-extension is semantically correct. |
|
| 555 | + | // For ULT: bltu gives identical results on sign- vs zero- |
|
| 556 | + | // extended W32 values (the relative ordering is preserved |
|
| 557 | + | // because the sign bit maps to the same half of 64-bit space). |
|
| 558 | + | // For EQ/NE: both extensions produce identical equality results. |
|
| 553 | 559 | if not aIsZero { emitSext(s.e, rs1, rs1, typ); } |
|
| 554 | 560 | if not bIsZero { emitSext(s.e, rs2, rs2, typ); } |
|
| 555 | - | } else if let case il::CmpOp::Ult = op { |
|
| 556 | - | if not aIsZero { emitZext(s.e, rs1, rs1, typ); } |
|
| 557 | - | if not bIsZero { emitZext(s.e, rs2, rs2, typ); } |
|
| 558 | - | } else if typ == il::Type::W32 { |
|
| 561 | + | } else if let case il::CmpOp::Slt = op { |
|
| 559 | 562 | if not aIsZero { emitSext(s.e, rs1, rs1, typ); } |
|
| 560 | 563 | if not bIsZero { emitSext(s.e, rs2, rs2, typ); } |
|
| 561 | 564 | } else { |
|
| 562 | 565 | if not aIsZero { emitZext(s.e, rs1, rs1, typ); } |
|
| 563 | 566 | if not bIsZero { emitZext(s.e, rs2, rs2, typ); } |