Hello gcc developers!
I am working on a new back end for my MRISC32 ISA [1], and I'm still very
new to gcc internals. I suspect that I will have more questions further
down the road, but let's start with this topic...
The MRISC32 ISA has instructions for setting a register based on the
outcome of a comparison. For instance:
slt s1, s2, s3
...which is equal to (in C):
int s1 = s2 < s3 ? -1 : 0;
Now, these compare instructions set the target register value to -1 (all
bits set to 1), rather than +1 (only LSB set to 1), which is not compatible
with the "lt", "eq" etc operators in gcc (from what I can see). This forces
me to add an extra "and" operation to mask out only the LSB of the result
when implementing the compare operations.
For instance:
(define_insn "*slt"
[(set (match_operand:SI 0 "register_operand" "=r")
(lt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")))]
""
"slt\t%0, %1, %2\;and\t%0, %0, #1")
From a functional point of view, it should not be necessary to do that mask
operation until the value "1" or "0" is actually needed for an arithmetic
operation (e.g. as is the case in the default implementation of adddi3).
Logical operations (and, or, xor etc) and conditional branches can use the
-1 just as well as the +1.
Question: Is there any way that I can avoid doing the extra "and" operation
in every instantiation of slt? For instance are there other insn:s that I
can define that gcc will recognize and use instead, or a machine
configuration that I can control to get a different behavior?
Best regards,
Marcus
[1]
https://github.com/mbitsnbites/gcc-mrisc32/tree/mbitsnbites/mrisc32/gcc/config/mrisc32