Improve instruction selection for SLT/ULT

6cd41da36ba1045497f1bfb6b30032c8311dc61669b59ad951edf5c6a56b3396
Alexis Sellier committed ago 1 parent 3d0bcffc
lib/std/arch/rv64/isel.rad +11 -0
538 538
539 539
            // Normalize sub-word operands so that both registers have the same
540 540
            // canonical representation. Without this, eg. `-1 : i8 ` loaded as
541 541
            // `0xFFFFFFFFFFFFFFFF` and `255 : i8` loaded as `0xFF` would compare
542 542
            // unequal even though they are the same 8-bit pattern.
543 +
            //
544 +
            // For SLT: sign-extension needed (signed comparison).
545 +
            // For ULT: zero-extension needed (unsigned magnitude comparison).
546 +
            // For EQ/NE with W32: sign-extension is cheaper.
547 +
            // For EQ/NE with W8/W16: keep zero-extension.
543 548
            // Skip extension for zero register.
544 549
            if let case il::CmpOp::Slt = op {
545 550
                if not aIsZero { emitSext(s.e, rs1, rs1, typ); }
546 551
                if not bIsZero { emitSext(s.e, rs2, rs2, typ); }
552 +
            } else if let case il::CmpOp::Ult = op {
553 +
                if not aIsZero { emitZext(s.e, rs1, rs1, typ); }
554 +
                if not bIsZero { emitZext(s.e, rs2, rs2, typ); }
555 +
            } else if typ == il::Type::W32 {
556 +
                if not aIsZero { emitSext(s.e, rs1, rs1, typ); }
557 +
                if not bIsZero { emitSext(s.e, rs2, rs2, typ); }
547 558
            } else {
548 559
                if not aIsZero { emitZext(s.e, rs1, rs1, typ); }
549 560
                if not bIsZero { emitZext(s.e, rs2, rs2, typ); }
550 561
            }
551 562
            // Block-argument moves must only execute on the taken path.