C compiler comparison - part two

Page 1/5
| 2 | 3 | 4 | 5

By PingPong

Prophet (3889)

PingPong's picture

09-04-2007, 21:08

Hi, all.
I've done some experiment on 'C' compilers.
the test program i've used is not purely cpu-intensive but more 'mixed'.
Basically it's a routine used to draw on screen2 circles used the well known bresenham algo that allow us to draw circles without doing any kind of floating point math ( and sure no trigonometric evaluations ).

I've compiled the following source under
SDCC, (latest nightly build) with optimizations in speed and
Hitech C 7.5 with all speed optimization on

Here it's the time i've got to draw 100 circles of increasing radius (0-100)
SDCC : 19 secs.
HT7.50: < 10 secs.

the code does not use bios or so dependant compiler features to make time results more independant.
Basically it set the screen mode, fillvrams
and using not optimized pure 'c' code interacts with vram.

The code is not hand-optimized to see how a good compiler could do in this circumstances

Anyone could test this source on other compilers? i'm really curious of the results.(I'm very interested on z88dk, IAR)
Here is the source:



#ifdef SDCC
	#include <stdio.h>
	#include <ioport.h>


	void di()
	{
		_asm
		di
		_endasm;
	}

	void ei()
	{
		_asm
		ei
		_endasm;
	}
#else
	#include <stdio.h>
	#include <sys.h>

	void di()
	{
		asm("di");
	}

	void ei()
	{
		asm("ei");
	}
#endif

void vdpsetreg (unsigned char regno, unsigned char value)
{
	di();
	#ifdef SDCC
		out(0x99, value);
		out(0x99, regno | 0x80);
	#else
		outp(0x99, value);
		outp(0x99, regno | 0x80);
	#endif
	ei();
}

unsigned char vrampeek(unsigned int addr)
{
	di();
	#ifdef SDCC
		out(0x99, addr & 255);
		out(0x99, (addr >> 8) & 0x3f);
	#else
		outp(0x99, addr & 255);
		outp(0x99, (addr >> 8) & 0x3f);
	#endif
	ei();
	#ifdef SDCC
		return in(0x98);
	#else
		return inp(0x98);
	#endif
}

void vrampoke(unsigned int addr, unsigned char byte)
{
	di();
	#ifdef SDCC
		out(0x99, addr & 255);
		out(0x99, 0x40 | ((addr >> 8) & 0x3f));
	#else
		outp(0x99, addr & 255);
		outp(0x99, 0x40 | ((addr >> 8) & 0x3f));
	#endif
	ei();
	#ifdef SDCC
		out(0x98, byte);
	#else
		outp(0x98, byte);
	#endif
}

void setpixel(unsigned char x, unsigned char y)
{
	int vramaddr = (x & 0xf8) + (y & 7) + (int)256 * (y>>3);
	vrampoke(vramaddr, vrampeek(vramaddr) | (128 >> (x & 7)) );
}

void sc2()
{
	unsigned char r;
	static unsigned char vdpregs[] = {0x02,0x60,0x06,0xFF, 0x03, 0x36, 0x07,0x04};
	for (r =0;r 
Login or register to post comments

By PingPong

Prophet (3889)

PingPong's picture

10-04-2007, 08:31

No one interested?
Results in my test give better performances on hitec c that is in contrast with ARTRAG's tests.

By cax

Prophet (3737)

cax's picture

10-04-2007, 09:07

Sure this comparison is very interesting, but I don't have enough hardware and compilers to help you with tests, and I am not sure whether making comparisons on emulator makes sense. So I decided to check this thread from time to time to see how the things are going.

By PingPong

Prophet (3889)

PingPong's picture

10-04-2007, 09:39

... making comparisons on emulator makes sense.
we are only comparing the quality of z80 code, not the emulators.
using the same emulator (in my test: bluemsx) result should not be influenced by the fact we test on emu.

Plus, consider that i'm not using any special feature here, (no VDP tricks, or raster int or so on) only z80 code, is tested.
Basically test could also be done on a z80 simulator.

The goal for me is only to see how is efficient the 'c' code generated.

When ARTRAG submitted the results on eratostene sieve, i've been a bit suspicius.
the fragment of code used, is a monolitic code, without calls between routines.

In a similar scenario the compiler does not have to do any kind of operations, such the prolog / epilog code to manage stack frame, nor does not need to manage parameter passing between routines.

So the tests with eratostene sieve it's not so accurate. In a real world you have to do with sub-routines, parameter coercion, stack frame management.

All these things severely impact on performances.

This is the main reason i've decided to test more in depth.

By PingPong

Prophet (3889)

PingPong's picture

10-04-2007, 13:35

Another good test is to test the efficiency of the floating point math. Does the z88dk routines be hand-optimized?

By ARTRAG

Enlighted (6845)

ARTRAG's picture

10-04-2007, 14:15

I'll try your code in IAR asap and I'll give you the asm
in order to make a comparison, anyway some low level
routines you define are already implemented in HITECH C v7.8
as macros (at least DI and EI). I think they are the same in v7.5.

PS
in order to shrink the code (not the result) you could use onlu in and out
and try macros like thos:

	#ifdef SDCC
	#define 	out 	out
	#define 	in	in
	#else
	#define 	out 	outp
	#define 	in	inp
	#endif

By PingPong

Prophet (3889)

PingPong's picture

10-04-2007, 14:39

welcome back ARTRAG. !

I'll try your code in IAR asap and I'll give you the asm
in order to make a comparison, anyway some low level
routines you define are already implemented in HITECH C v7.8
as macros (at least DI and EI). I think they are the same in v7.5.
PS
in order to shrink the code (not the result) you could use onlu in and out
and try macros like thos:

	#ifdef SDCC

Sure, but yesterday i've got some throuble with conditional defines, and i've resort to this less elegant code.
Please, let the macro DI/EI as call.

This is to verify if, when calling a void f(void) function the compiler omits the prologue/epilogue stack frame management code in some situations.

As said the code is not very opt. but faster than the standard circle routine in msx-basic
(Obvious, no circle sector, no ellipse or aspect ratio, only manage the pattern area, not color attributes)

Cool

By ARTRAG

Enlighted (6845)

ARTRAG's picture

10-04-2007, 16:37

This is IAR, I didn't executed it, can anyone run it?

##############################################################################
#                                                                            #
# IAR Z80/64180 C-Compiler V4.06A/WIN                                        #
#                                                                            #
#       Compile time  =  10/Apr/2007  16:34:29                               #
#       Target option =  Z80                                                 #
#       Memory model  =  large                                               #
#       Source file   =  d:\iar\debug\list\circles.c                         #
#       List file     =  d:\iar\debug\list\circles.lst                       #
#       Object file   =  d:\iar\debug\obj\circles.r01                        #
#       ASM file      =  d:\iar\debug\list\circles.s01                       #
#       Command line  =  -v0 -ml -uuar -OD:\IAR\Debug\Obj\ -d -e -c -K -gA   #
#                        -s9 -RCODE -r0 -LD:\IAR\Debug\List\ -q -T -t8       #
#                        -AD:\IAR\Debug\List\ -X                             #
#                        -ID:\IAR\IAR ewz80\z80\inc\                         #
#                        D:\IAR\Debug\List\circles.c                         #
#                                                                            #
#                           Copyright 2001 IAR Systems. All rights reserved. #
##############################################################################

   \   0000                    NAME    circles(16)
   \   0000                    RSEG    CODE(0)
   \   0000                    RSEG    TEMP(0)
   \   0000                    RSEG    IDATA0(0)
   \   0000                    RSEG    CDATA0(0)
   \   0000                    PUBLIC  circle
   \   0000                    PUBLIC  di
   \   0000                    PUBLIC  ei
   \   0000                    PUBLIC  main
   \   0000                    PUBLIC  plotpoints
   \   0000                    PUBLIC  sc2
   \   0000                    PUBLIC  setpixel
   \   0000                    PUBLIC  vdpsetreg
   \   0000                    PUBLIC  vraminit
   \   0000                    PUBLIC  vrampeek
   \   0000                    PUBLIC  vrampoke
   \   0000                    EXTERN  ?CLZ80L_4_06_L00
   \   0000                    EXTERN  ?UC_RSH_L01
   \   0000                    RSEG    CODE
   \   0000            di:
      1          #define outp output8
      2          #define inp input8
      3          
      4          #ifdef SDCC
     22          #else
     23                  #include <stdio.h>
     24                  #include "intrz80.h"
     25          
     26                  void di(void)
     27                  {
   \   0000  F3                DI
     28                          disable_interrupt();
   \   0001  C9                RET
   \   0002            ei:
     29                  }
     30          
     31                  void ei(void)
     32                  {
   \   0002  FB                EI
     33                          enable_interrupt();
   \   0003  C9                RET
   \   0004            vdpsetreg:
     34                  }
     35          #endif
     36          
     37          void vdpsetreg (unsigned char regno, unsigned char value)
   \   0004  D5                PUSH    DE
     38          {
   \   0005  CD0000            CALL    di
     39                  di();
     40                  #ifdef SDCC
     43                  #else
   \   0008  79                LD      A,C
   \   0009  D399              OUT     (153),A
     44                          outp(0x99, value);
   \   000B  43                LD      B,E
   \   000C  CBF8              SET     7,B
   \   000E  78                LD      A,B
   \   000F  D399              OUT     (153),A
     45                          outp(0x99, regno | 0x80);
     46                  #endif
   \   0011  CD0200            CALL    ei
     47                  ei();
   \   0014  E1                POP     HL
   \   0015  C9                RET
   \   0016            vrampeek:
     48          }
     49          
     50          unsigned char vrampeek(unsigned int addr)
   \   0016  DDE5              PUSH    IX
   \   0018  D5                PUSH    DE
   \   0019  DDE1              POP     IX
     51          {
   \   001B  CD0000            CALL    di
     52                  di();
     53                  #ifdef SDCC
     56                  #else
   \   001E  7B                LD      A,E
   \   001F  D399              OUT     (153),A
     57                          outp(0x99, addr & 255);
   \   0021  DDE5              PUSH    IX
   \   0023  E1                POP     HL
   \   0024  7C                LD      A,H
   \   0025  E63F              AND     63
   \   0027  D399              OUT     (153),A
     58                          outp(0x99, (addr >> 8) & 0x3f);
     59                  #endif
   \   0029  CD0200            CALL    ei
     60                  ei();
     61                  #ifdef SDCC
     63                  #else
   \   002C  DB98              IN      A,(152)
     64                          return inp(0x98);
     65                  #endif
   \   002E  DDE1              POP     IX
   \   0030  C9                RET
   \   0031            vrampoke:
     66          }
     67          
     68          void vrampoke(unsigned int addr, unsigned char byte)
   \   0031  DDE5              PUSH    IX
   \   0033  C5                PUSH    BC
   \   0034  D5                PUSH    DE
   \   0035  DDE1              POP     IX
     69          {
   \   0037  CD0000            CALL    di
     70                  di();
     71                  #ifdef SDCC
     74                  #else
   \   003A  7B                LD      A,E
   \   003B  D399              OUT     (153),A
     75                          outp(0x99, addr & 255);
   \   003D  DDE5              PUSH    IX
   \   003F  E1                POP     HL
   \   0040  6C                LD      L,H
   \   0041  CBBD              RES     7,L
   \   0043  CBF5              SET     6,L
   \   0045  7D                LD      A,L
   \   0046  D399              OUT     (153),A
     76                          outp(0x99, 0x40 | ((addr >> 8) & 0x3f));
     77                  #endif
   \   0048  CD0200            CALL    ei
     78                  ei();
     79                  #ifdef SDCC
     81                  #else
   \   004B  79                LD      A,C
   \   004C  D398              OUT     (152),A
     82                          outp(0x98, byte);
     83                  #endif
   \   004E  E1                POP     HL
   \   004F  DDE1              POP     IX
   \   0051  C9                RET
   \   0052            setpixel:
     84          }
     85          
     86          void setpixel(unsigned char x, unsigned char y)
   \   0052  D5                PUSH    DE
   \   0053  79                LD      A,C
     87          {
   \   0054  CB39              SRL     C
   \   0056  CB39              SRL     C
   \   0058  CB39              SRL     C
   \   005A  41                LD      B,C
   \   005B  0E00              LD      C,0
   \   005D  61                LD      H,C
   \   005E  E607              AND     7
   \   0060  6F                LD      L,A
   \   0061  09                ADD     HL,BC
   \   0062  E5                PUSH    HL
   \   0063  7B                LD      A,E
   \   0064  E6F8              AND     248
   \   0066  4F                LD      C,A
   \   0067  0600              LD      B,0
   \   0069  E1                POP     HL
   \   006A  09                ADD     HL,BC
   \   006B  220000            LD      (?0010),HL
     88                  int vramaddr = (x & 0xf8) + (y & 7) + (int)256 * (y>>3);
   \   006E  EB                EX      DE,HL
   \   006F  CD1600            CALL    vrampeek
   \   0072  F5                PUSH    AF
   \   0073  210200            LD      HL,2
   \   0076  39                ADD     HL,SP
   \   0077  7E                LD      A,(HL)
   \   0078  E607              AND     7
   \   007A  47                LD      B,A
   \   007B  3E80              LD      A,128
   \   007D  CD0000            CALL    ?UC_RSH_L01
   \   0080  47                LD      B,A
   \   0081  F1                POP     AF
   \   0082  B0                OR      B
   \   0083  4F                LD      C,A
   \   0084  ED5B0000          LD      DE,(?0010)
   \   0088  CD3100            CALL    vrampoke
     89                  vrampoke(vramaddr, vrampeek(vramaddr) | (128 >> (x & 7)) );
   \   008B  E1                POP     HL
   \   008C  C9                RET
   \   008D            sc2:
     90          }
     91          
     92          void sc2(void)
   \   008D  C5                PUSH    BC
   \   008E  D5                PUSH    DE
     93          {
     94                  unsigned char r;
     95                  static unsigned char vdpregs[] = {0x02,0x60,0x06,0xFF, 0x03, 0x36, 0x07,0x04};
   \   008F  AF                XOR     A
   \   0090  320200            LD      (?0010+2),A
   \   0093            ?0013:
   \   0093  3A0200            LD      A,(?0010+2)
   \   0096  FE08              CP      8
   \   0098  3015              JR      NC,?0012
   \   009A            ?0014:
     96                  for (r =0;r

This is more readable

	NAME	circles(16)
	RSEG	CODE(0)
	RSEG	TEMP(0)
	RSEG	IDATA0(0)
	RSEG	CDATA0(0)
	PUBLIC	circle
	PUBLIC	di
	PUBLIC	ei
	PUBLIC	main
	PUBLIC	plotpoints
	PUBLIC	sc2
	PUBLIC	setpixel
	PUBLIC	vdpsetreg
	PUBLIC	vraminit
	PUBLIC	vrampeek
	PUBLIC	vrampoke
	EXTERN	?CLZ80L_4_06_L00
	EXTERN	?UC_RSH_L01
	RSEG	CODE
di:
; 1.	#define outp output8
; 2.	#define inp input8
; 3.	
; 4.	#ifdef SDCC
; 22.	#else
; 23.	        #include <stdio.h>
; 24.	        #include "intrz80.h"
; 25.	
; 26.	        void di(void)
; 27.	        {
	DI
; 28.	                disable_interrupt();
	RET
ei:
; 29.	        }
; 30.	
; 31.	        void ei(void)
; 32.	        {
	EI
; 33.	                enable_interrupt();
	RET
vdpsetreg:
; 34.	        }
; 35.	#endif
; 36.	
; 37.	void vdpsetreg (unsigned char regno, unsigned char value)
	PUSH	DE
; 38.	{
	CALL	di
; 39.	        di();
; 40.	        #ifdef SDCC
; 43.	        #else
	LD	A,C
	OUT	(153),A
; 44.	                outp(0x99, value);
	LD	B,E
	SET	7,B
	LD	A,B
	OUT	(153),A
; 45.	                outp(0x99, regno | 0x80);
; 46.	        #endif
	CALL	ei
; 47.	        ei();
	POP	HL
	RET
vrampeek:
; 48.	}
; 49.	
; 50.	unsigned char vrampeek(unsigned int addr)
	PUSH	IX
	PUSH	DE
	POP	IX
; 51.	{
	CALL	di
; 52.	        di();
; 53.	        #ifdef SDCC
; 56.	        #else
	LD	A,E
	OUT	(153),A
; 57.	                outp(0x99, addr & 255);
	PUSH	IX
	POP	HL
	LD	A,H
	AND	63
	OUT	(153),A
; 58.	                outp(0x99, (addr >> 8) & 0x3f);
; 59.	        #endif
	CALL	ei
; 60.	        ei();
; 61.	        #ifdef SDCC
; 63.	        #else
	IN	A,(152)
; 64.	                return inp(0x98);
; 65.	        #endif
	POP	IX
	RET
vrampoke:
; 66.	}
; 67.	
; 68.	void vrampoke(unsigned int addr, unsigned char byte)
	PUSH	IX
	PUSH	BC
	PUSH	DE
	POP	IX
; 69.	{
	CALL	di
; 70.	        di();
; 71.	        #ifdef SDCC
; 74.	        #else
	LD	A,E
	OUT	(153),A
; 75.	                outp(0x99, addr & 255);
	PUSH	IX
	POP	HL
	LD	L,H
	RES	7,L
	SET	6,L
	LD	A,L
	OUT	(153),A
; 76.	                outp(0x99, 0x40 | ((addr >> 8) & 0x3f));
; 77.	        #endif
	CALL	ei
; 78.	        ei();
; 79.	        #ifdef SDCC
; 81.	        #else
	LD	A,C
	OUT	(152),A
; 82.	                outp(0x98, byte);
; 83.	        #endif
	POP	HL
	POP	IX
	RET
setpixel:
; 84.	}
; 85.	
; 86.	void setpixel(unsigned char x, unsigned char y)
	PUSH	DE
	LD	A,C
; 87.	{
	SRL	C
	SRL	C
	SRL	C
	LD	B,C
	LD	C,0
	LD	H,C
	AND	7
	LD	L,A
	ADD	HL,BC
	PUSH	HL
	LD	A,E
	AND	248
	LD	C,A
	LD	B,0
	POP	HL
	ADD	HL,BC
	LD	(?0010),HL
; 88.	        int vramaddr = (x & 0xf8) + (y & 7) + (int)256 * (y>>3);
	EX	DE,HL
	CALL	vrampeek
	PUSH	AF
	LD	HL,2
	ADD	HL,SP
	LD	A,(HL)
	AND	7
	LD	B,A
	LD	A,128
	CALL	?UC_RSH_L01
	LD	B,A
	POP	AF
	OR	B
	LD	C,A
	LD	DE,(?0010)
	CALL	vrampoke
; 89.	        vrampoke(vramaddr, vrampeek(vramaddr) | (128 >> (x & 7)) );
	POP	HL
	RET
sc2:
; 90.	}
; 91.	
; 92.	void sc2(void)
	PUSH	BC
	PUSH	DE
; 93.	{
; 94.	        unsigned char r;
; 95.	        static unsigned char vdpregs[] = {0x02,0x60,0x06,0xFF, 0x03, 0x36, 0x07,0x04};
	XOR	A
	LD	(?0010+2),A
?0013:
	LD	A,(?0010+2)
	CP	8
	JR	NC,?0012
?0014:
; 96.	        for (r =0;r		

By PingPong

Prophet (3889)

PingPong's picture

10-04-2007, 19:12

Hey, ARTRAG, what is blocking you to test it? . You do not know how to make .com? or what?

By msd

Paragon (1472)

msd's picture

10-04-2007, 19:37

Do those compilers support the inline statement?

By dvik

Prophet (2200)

dvik's picture

10-04-2007, 19:55

msd, in c, you usually use the static keyword to inline methods. Most compilers I've seen will inline static methods when optimizations are turned on.

Page 1/5
| 2 | 3 | 4 | 5