This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Asm code runs slower with -O


Hello, 

  I'm attaching a source file which contains two checksum routines, one 
written in asm and the other in plain C.
  If I compile with -O or -O2, the program runs about 1.3-1.5 times SLOWER 
than with no optimizations. My compiler is gcc-2.95.3 and my test machine is 
an AMD Athlon @ 1145 Mhz.
  Please bear with me if there's something wrong with my asm routine, since 
I'm just beginning to learn how gcc inline asm works.

/*
*	Benchmark for udp checksum code, C version or asm version
*/
#include <sys/timeb.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

//typedef unsigned int uint;
typedef unsigned short word;
typedef unsigned long long uint64;

uint64 get_time(){
	struct timeb	tm;
	uint64			ret;
	
	ftime(&tm);
	ret = tm.time;
	ret *= 1000;
	ret += tm.millitm;
	return ret;
}
                            
int main(){
	char		buf[1024];
	char		pseudo[12];
	uint*		p;
	int			i, cnt;
	uint		a, b, sum, len, os, proto_and_len;
	uint64		st, ed;

	/* 
	*  We use a random len because we don't want gcc to use it as a constant,
	* since we want to simulate real-life conditions
	*/	
	srand(time(0));
	len = 1000 + (uint) (24.0*rand()/(RAND_MAX+1.0));
	if(len % 4)
		len += 4 - (len%4);
	printf("len: %d\n", len);
	
	a = 0xababf1f1;
	b = 0xcccccccc;
	for(i=0; i<1024; i++)
		buf[i]=(char) (256.0*rand()/(RAND_MAX+1.0));

	*(uint*)pseudo = a;
	*(uint*)(pseudo+4) = b;
	*(uint*)(pseudo+8) = (len<<16)+17*256;
	
	/* ASM VERSION */	
	st = get_time();
	proto_and_len = (len<<16)+17*256;
	for(cnt=0; cnt<100000; cnt++){
		__asm__ __volatile__ ("
			/* sum the pseudo-header values */
			movl	%1, %0
			addl	%2, %0
			adcl	%3, %0
			adcl	$0, %0
			/* fold and complement */
			movl	%0, %%ebx
			shrl	$16, %0
			addw	%%bx, %w0
			adcl	$0, %0
			notl	%0
			andl	$0x0000ffff, %0
			/* add packet */
			shrl	$2, %%ecx
			clc
		1:	adcl	(%5), %0
			lea		4(%5), %5
			decl	%%ecx
			jne		1b
			adcl	$0, %0
			/* fold and complement */
			movl	%0, %%ebx
			shrl	$16, %0
			addw	%%bx, %w0
			adcl	$0, %0
			notl	%0
			andl	$0x0000ffff, %0
		"	
		/* the damn compiler uses esi for sum if we say "=r" here !! */
		: "=a"(sum)
		: "g"(a), "g"(b), "g"(proto_and_len), "c"(len), "S"(buf)
		: "%ebx"
		);
	}
	
	ed = get_time();
	printf("sum: %x; elapsed time: %d\n", sum, ed-st);

	/* PLAIN C VERSION */
	st = get_time();
	for(cnt=0; cnt<100000; cnt++){	
		sum = 0;
		p = (typeof(p))pseudo;
		i = 12;
		while( i > 1 )  {
			os = sum;
			sum += *p;
			if(sum < os)
				++sum;
			++p;
			i -= sizeof(*p);
		}
		/* Fold 32-bit sum to 16 bits */
		while (sum>>16)
			sum = (sum & 0xffff) + (sum >> 16);
		sum = (~sum) & 0x0000ffff;
	
		p = (typeof(p))buf;
		i = 1024;
		while( i > 1 )  {
			os = sum;
			sum += *p;
			if(sum < os)
				++sum;
			++p;
			i -= sizeof(*p);
		}
		/* Fold 32-bit sum to 16 bits */
		while (sum>>16)
			sum = (sum & 0xffff) + (sum >> 16);
		sum = (~sum) & 0x0000ffff;
	}
	ed = get_time();
	printf("sum: %x; elapsed time: %d\n", sum, ed-st);
 
	return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]