[fpc-devel] Constant eval (and dead code removal) - comparing 2 methods for being the same.
Martin Frb
lazarus at mfriebe.de
Wed Oct 1 12:46:51 CEST 2025
In the code
if true then begin
write(1);
end
else begin
write(2);
end;
the "else" block will not generate code (at least O2 and higher).
But
TFoo = class
procedure MyFoo;
end;
X = class(TFoo)
end;
//if @X.MyFoo = @TFoo.MyFoo then begin
if @TFoo.MyFoo = @TFoo.MyFoo then begin
write(1);
end
else begin
write(2);
end;
Does not detect this at compile time.
Note, that this is not on an instance, this is on the actual class => so
it is known.
Is there any way to get that optimize the "else" block away (or the
"then" if the compare goes the other way)?
I can't just compare the classes, as subclasses can have the same method
(if it isn't overridden/reintroduced)
Background:
This seems useless in the above example.
But I want to to that in a generic, and I am testing if the method on
the generic param is the same method as on a specific known class.
The best part is, that in the specialized generic (probably by the
peephole opt) the asm goes
# if @A.MyFoo = @TFoo.MyFoo then begin
leaq P$PROJECT1$_$TFOO_$__$$_MYFOO(%rip),%rax
cmpq %rax,%rax
jne .Lj14
And rax is always equal to rax, so the conditional jump always does the
same. But it still is a conditional jump (though I guess the branch
prediction in the CPU will be overjoyed).
----------------------------------------------
program project1;
{$Mode objfpc}
type
TFoo = class
procedure MyFoo;
end;
TFoo2 = class
procedure MyFoo;
end;
generic TBar<A> = class
procedure MyBar;
end;
procedure TFoo.MyFoo;
begin
write;
end;
procedure TFoo2.MyFoo;
begin
write;
end;
procedure TBar.MyBar;
begin
if @A.MyFoo = @TFoo.MyFoo then begin
write(1);
end
else begin
write(2);
end;
end;
type
X = class(TFoo) end;
TB1 = specialize TBar<TFoo>;
TB2 = specialize TBar<TFoo2>;
procedure xyz;
begin
//if @X.MyFoo = @TFoo.MyFoo then begin
if @TFoo.MyFoo = @TFoo.MyFoo then begin
write(1);
end
else begin
write(2);
end;
end;
procedure xyz2;
begin
if true then begin
write(1);
end
else begin
write(2);
end;
end;
var
b1: TB1;
b2: TB2;
begin
xyz;
xyz2;
b1.MyBar;
b2.MyBar;
end.
More information about the fpc-devel
mailing list