I completely agree with you on 0/1 vs 0/-1 for SLT and you can easily find me saying so. For example:
https://lists.riscv.org/g/tech-bitmanip/message/496It was an error, though a rather minor one, to follow the C language so closely. I can and have pointed out other minor mistakes in RISC-V in the past -- none of them serious enough to abandon it and start over.
I'll quote myself from there, below.
32 bits is not such a huge instruction. ARM decided it's good enough for their new(ish) 64 bit ISA,
and it's about the average size of x86_64 instructions.
Original RISC-V (v1.0) has only and exactly the instructions needed to implement C. That's enough for many or most applications, and will be available as a support option forever. The upcoming RVA22 specification for Applications Processors, which will be ratified before the end of the year includes an SVE-like vector extension and also Bit Manipulation extensions (along with many others). The Zbb (Basic bit-manipulation) extension includes cpop along with clz and ctz and rotate. There is also andn, orn, xnor, max, maxu, min, minu, sext.b, sext.h, zext.h, and rev8 (reverse bytes in a register). Plus a unique instruction orc.b which replaces any non-zero byte in the source operand with all ones. There is also scalar crypto and cache manipulation (prefetch, flush etc).
Perhaps RVA22 is your hypothetical Risc-6.
-----
There are five reasons you might use SLT / SLTU, in (I think) descending order of how common they are, and the implications had -1 been used instead of 1:
1) to generate a zero/non-zero value. No difference.
2) to generate a mask. Using 0 and -1 is better, saving a NEG or a subtract 1, depending on whether you reverse the condition or not.
3) to generate a value that can be AND / OR / XOT etc with other such values. No difference.
4) to assign to a canonical C/C++ true/false, or mix with them using AND / OR / XOR. Worse -- have to do an ANDI #1 before using the final result.
5) to generate a canonical C true/false and add or subtract it from something. No difference. Just flip add to subtract or vice versa.
Interestingly, a time when you do want 0 or 1 is the examples in the original superoptimiser paper from 1987.
https://web.stanford.edu/class/cs343/resources/superoptimize...
They first considered the function:
int signum (int x) {
if(x > 0) return I;
else if(x
They showed the superoptimiser finding the following unexpected 68020 sequence, making use of the carry flag:
(x in dO)
add.l d0,d0 ;add dO to itself
subx.l dl,dl ;subtract (dl + Carry) from dl
negx.l dO ;put (0 - dO - Carry) into dO
addx.l dl,dl ;add (dl + Carry) to dl
(signum(x) in dl} (4 instructions}
This is much more straightforward on RISC-V:
(x in a0)
slt a1,a0,zero # a1 = 1 if x is negative, 0 if 0 or positive
slt a0,zero,a0 # a0 = 1 if x is positive, 0 if 0 or negative
sub a0,a0,a1 # 1-0 = 1 if positive, 0-0 = 0 if zero, 0-1 = -1 if negative
-----