[Turbo Pascal] Q&A official thread

Page 15/17
8 | 9 | 10 | 11 | 12 | 13 | 14 | | 16 | 17

By rolandve

Master (254)

rolandve's picture

05-05-2020, 18:17

Sadly enough my assembly skills are useless for the free pascal people. Otherwise I would have jumped on-board.

By PascalDragon

Supporter (9)

PascalDragon's picture

07-05-2020, 11:44

Especially for the development of a new target assembly skills are important.

The code generator backend for Z80 still has bugs and shortcomings, so you could check whether the compiler generates correct assembly code or might be able to generate better code. Also there is the assembly reader that can be checked for bugs, cause unlike Turbo Pascal 3 with its Inline() statement FPC has mnemonic based inline assembly which is parsed by a platform specific assembler reader.

Then there would be optimizations based on the instructions. The code generator tries to generate rather straight forward code, but the instruction based optimizer might be able to improve this (for example on x86 this reduces unnecessary register moves), so you could identify such situations.

And finally there are the RTL helpers that are for example used for sets, strings or Int64 maths. Those are currently implemented using generic Pascal code, but they can be redirected to platform specific implementations that are usually implemented using assembly and can even avoid setting up a stackframe. You can find these here (though these include files are mostly empty right now as these implementations are missing).

By rolandve

Master (254)

rolandve's picture

07-05-2020, 21:58

I am looking for a shortcut. In code you often do checks like If ( Var < > # ) so you can get a true/false evaluation. Sometimes its more simple like if ( X > 0 ). In some lazy languages true or false are defined as False:=0 and True any other value so this evaluation then becomes if (X) which saves a check and some cpu cycles.

Is there a way to do this in TP? I can imagine taking the address of a boolean and have an assembly program verify this and return the result to the boolean, but that is way more work which doesn't seem much faster and requires more memory.
Thanks.

By Manuel

Ascended (17942)

Manuel's picture

08-05-2020, 00:16

Why do you want this, does it really add so much value? I prefer more exact and clear language, this also avoids bugs. Booleans be booleans!

By rolandve

Master (254)

rolandve's picture

08-05-2020, 09:30

Its a matter of nano-speed I suppose. You verify if something is initialised (>0) or not (0). Having to do a numerical comparison for this is a good way, but when you know that the compiler evaluates this towards a True/False (internally represented by a number) my desire to keep it short makes me want try and skip these steps.

So to answer your question: it does not really add value except knowing that this is about the most effective way to do it.

By pgimeno

Champion (289)

pgimeno's picture

08-05-2020, 14:24

If the compiler does not optimize a comparison with zero to an OR A or similar, that's a shortcoming in the compiler. These are the kind of things that it should do automatically for you.

By PascalDragon

Supporter (9)

PascalDragon's picture

08-05-2020, 14:49

rolandve wrote:

I am looking for a shortcut. In code you often do checks like If ( Var < > # ) so you can get a true/false evaluation. Sometimes its more simple like if ( X > 0 ). In some lazy languages true or false are defined as False:=0 and True any other value so this evaluation then becomes if (X) which saves a check and some cpu cycles.

Is there a way to do this in TP? I can imagine taking the address of a boolean and have an assembly program verify this and return the result to the boolean, but that is way more work which doesn't seem much faster and requires more memory.
Thanks.

There isn't really that much difference between comparing an integer value to 0 or checking whether a Boolean is True or False.

Take this example:

procedure Test;
var
  u: UInt8;
  s: Int8;
  b: Boolean;
begin
  u := 42;
  s := 42;
  b := True;
  if u > 0 then ;
  if s <> 0 then ;
  if b then ;
end;

FPC currently generates this code for Z80:

	.section .text.n_p$thelloworld_$$_test,"acrx"
	.globl P$THELLOWORLD_$$_TEST
P$THELLOWORLD_$$_TEST:
.Lc2:
; [thelloworld.pp]
; [8] begin
		push	ix
.Lc3:
.Lc4:
		ld	ix,0
		add	ix,sp
.Lc5:
		ld	hl,-3
		add	hl,sp
		ld	sp,hl
; Var u located at ix-1, size=OS_8
; Var s located at ix-2, size=OS_S8
; Var b located at ix-3, size=OS_8
; [9] u := 42;
		ld	(ix-1),42
; [10] s := 42;
		ld	(ix-2),42
; [11] b := True;
		ld	(ix-3),1
; [12] if u > 0 then ;
		ld	a,0
		cp	a,(ix-1)
		jp	C,.Lj5
		jp	.Lj6
.Lj6:
.Lj5:
; [13] if s <> 0 then ;
		ld	a,(ix-2)
		ld	b,a
		ld	a,b
		cp	a,0
		jp	NZ,.Lj7
		jp	.Lj8
.Lj8:
.Lj7:
; [14] if b then ;
		ld	a,(ix-3)
		ld	b,a
		ld	a,b
		cp	a,0
		jp	NZ,.Lj9
		jp	.Lj10
.Lj10:
.Lj9:
; [15] end;
		ld	sp,ix
		pop	ix
		ret
.Lc1:

If you ignore the superfluous moves from a to b and back again then we essentially have this for the comparisons:

; [12] if u > 0 then ;
		ld	a,0
		cp	a,(ix-1)
		jp	C,.Lj5
		jp	.Lj6
.Lj6:
.Lj5:
; [13] if s <> 0 then ;
		ld	a,(ix-2)
		cp	a,0
		jp	NZ,.Lj7
		jp	.Lj8
.Lj8:
.Lj7:
; [14] if b then ;
		ld	a,(ix-3)
		cp	a,0
		jp	NZ,.Lj9
		jp	.Lj10
.Lj10:
.Lj9:

Except for the compiler swapping the register value and the compare value for the unsigned case all three are essentially the same except for the condition flag for the JP instruction. Even if you'd compare against a specific number instead of 0 there wouldn't be much of a difference (as long as it can be used as an immediate).

Is this what you meant?

By rolandve

Master (254)

rolandve's picture

08-05-2020, 15:37

Thank you for you long answer. This is a purely for fun subject. So please don't spend too much time on it. Assembler was never this issue because Boolean is an abstract that is used by the compiler and the developer. The pascal compiler, by design, has strict enforcement of types. An IF evaluates to a True or False. Thats how a compiler should be designed otherwise IF wouldn't exist. The compiler does this by creating the equivalent codes like you write above. However, TP does not support the ' if b then' language construct. It has a 'if value1 condition value2' rule and the result (a logical flag) is then used for choosing the first block or the else block. The B in 'if b then' itself is not accepted as a pre-calculated boolean. Is this a problem.. no.

By PascalDragon

Supporter (9)

PascalDragon's picture

08-05-2020, 16:35

rolandve wrote:

Thank you for you long answer. This is a purely for fun subject. So please don't spend too much time on it.

Oh, I enjoy such things such things as well. I wouldn't work on a compiler in my free time otherwise after all. Wink

rolandve wrote:

The compiler does this by creating the equivalent codes like you write above. However, TP does not support the ' if b then' language construct. It has a 'if value1 condition value2' rule and the result (a logical flag) is then used for choosing the first block or the else block. The B in 'if b then' itself is not accepted as a pre-calculated boolean. Is this a problem.. no.

Are sure about that? I just tested Borland Turbo Pascal 3.00A on x86 and there the following program compiles:

program thello;

var
  b: Boolean;
begin
  b := True;
  if b then
    Writeln('True');
end.

That is because an if-statement is not defined as "if Value1 Condition Value2 then Statement", but as "if Expression then Statement", whereby "Expression" needs to evaluate to Boolean (so "if 1 then" is not allowed, just as "if SomeInt then" isn't, but "if SomeBoolean then" is allowed).

By rolandve

Master (254)

rolandve's picture

08-05-2020, 20:36

PascalDragon wrote:
rolandve wrote:

Thank you for you long answer. This is a purely for fun subject. So please don't spend too much time on it.

Oh, I enjoy such things such things as well. I wouldn't work on a compiler in my free time otherwise after all. Wink

rolandve wrote:

The compiler does this by creating the equivalent codes like you write above. However, TP does not support the ' if b then' language construct. It has a 'if value1 condition value2' rule and the result (a logical flag) is then used for choosing the first block or the else block. The B in 'if b then' itself is not accepted as a pre-calculated boolean. Is this a problem.. no.

Are sure about that? I just tested Borland Turbo Pascal 3.00A on x86 and there the following program compiles:

program thello;

var
  b: Boolean;
begin
  b := True;
  if b then
    Writeln('True');
end.

That is because an if-statement is not defined as "if Value1 Condition Value2 then Statement", but as "if Expression then Statement", whereby "Expression" needs to evaluate to Boolean (so "if 1 then" is not allowed, just as "if SomeInt then" isn't, but "if SomeBoolean then" is allowed).

Your example works, but I am not assigning booleans to variables, but bytes or integers Smile

My case is about the situation where B is not a boolean but a number. Somewhere TP assigns a number to True or False (its byte size). What.you call expression is what I refer to when I say: value condition value, so the expression can be if (B > 0) . My question is: how can I trick TP in to accepting an integer as a boolean. That way you don't need an expression B > 0 but B becomes the result of the evaluation.

Page 15/17
8 | 9 | 10 | 11 | 12 | 13 | 14 | | 16 | 17