variable_in_register=0 and variable_in_register<>0 comparisons are optimized to use "test" instead of "cmp" based on the zero flag. This means we have something like:
if variable_in_register<>0 then variable_in_register:=0;
testq %rax,%rax
je .Lj6
movq $0,%rax
When comparing for sign, fpc produces the following code:
if variable_in_register<0 then variable_in_register:=0;
cmpq $0,%rax
jnl .Lj6
movq $0,%rax
When dealing with "<0" and ">=0", I'd like "test" to be used instead of "cmp", too.
I've looked at compiler/i386/popt386.pas and I've seen:
A_CMP:
begin
if (taicpu(p).oper[0]^.typ = top_const) and
(taicpu(p).oper[0]^.val = 0) and
(taicpu(p).oper[1]^.typ = top_reg) then
{change "cmp $0, %reg" to "test %reg, %reg"}
begin
taicpu(p).opcode := A_TEST;
taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
continue;
end;
end;
So, I've said to myself that the "cmp" should have already been changed with "test". Paying further attention I've noticed that "jnl" would not work with "test" because "jnl" involves the overflow flag.
Now, I'm thinking that maybe if "jnl" would be replaced with "jns" at variable_in_register<0 then the peephole optimizer might do the job.
If I'm on the right track, where do I have to look further?
P.S. It should be obvious to you that I'm not experienced with compiler internals and I couldn't find documentation regarding how the compiler optimizes the code.