[gnu.gcc.bug] 68000 code generation

richards@EDDIE.MIT.EDU (Richard Sewards) (06/22/89)

I've found a code generation bug in gcc 1.34 with the 68000 code generator.
The following is the assembler output (and corresponding source lines) where
the problem occurs and after that I'm including the entire (preprocessed)
source file which generates the bug with comments at the lines where the
problem is.

The problems is that for register pointer variables compared with 0 a
word comparison is done instead of a long comparison.

Comilation command is :
	gcc68 -m68000 -fomit-frame-pointer -O -W -Wcomment -Wreturn-type
	      -Wunused -Wcast-qual -nostdinc -g  -S -o t.S -c t.c


Assembler output:
		#NO_APP
		gcc_compiled.:
		Ltext:
		.text
			.even
		.globl _f
		_f:
#| line 0     |	char	*a_p[8] ;
#| line 1     |	
#| line 2     |	void
#| line 3     |	f(sp)
#| line 4     |	char **sp ;
			moveml #0x2030,sp@-
			movel sp@(16),a3
		LBB2:
#| line 5     |	{
#| line 6     |	    char  *p ;
#| line 7     |	    int   i = 8 ;
			moveq #8,d2
#| line 8     |	
#| line 9     |	    do {
		L2:
#| line 10    |		p = *sp ;
			movel a3@,a2
#| line 11    |		
#| line 12    |		/* The test for p non-null does a
#| line 13    |		 * word comparison instead of a long
#| line 14    |		 * comparison.
#| line 15    |		 */
#| line 16    |		if (p && (*p != '\0')) {
			cmpw #0,a2
			jeq L4
			tstb a2@
			jeq L4
#| line 17    |		    *sp = p + strlen(p) ;
			movel a2,sp@-
			jbsr _strlen
			addl d0,a2
			movel a2,a3@
			addqw #4,sp
		L4:
#| line 18    |		}
#| line 19    |	    } while (--i != 0) ;
			subql #1,d2
			jne L2
		LBE2:
#| line 20    |	}
			moveml sp@+,#0xc04
			rts
			.even
		.globl _g
		_g:
#| line 21    |	
#| line 22    |	int
#| line 23    |	g(p)
#| line 24    |	char *p ;
#| line 25    |	{
#| line 26    |	    /* This test of the pointer does a
#| line 27    |	     * long comparison.
#| line 28    |	     */
#| line 29    |	    return p != 0 ;
			tstl sp@(4)
			sne d0
			moveq #1,d1
			andl d1,d0
#| line 30    |	}
			rts
		.comm _a_p,32

C source :---------------------------------------------------------------------
char	*a_p[8] ;

void
f(sp)
char **sp ;
{
    char  *p ;
    int   i = 8 ;

    do {
	p = *sp ;
	
	/* The test for p non-null does a
	 * word comparison instead of a long
	 * comparison.
	 */
	if (p && (*p != '\0')) {
	    *sp = p + strlen(p) ;
	}
    } while (--i != 0) ;
}

int
g(p)
char *p ;
{
    /* This test of the pointer does a
     * long comparison.
     */
    return p != 0 ;
}

-- 
Richard Sewards                      Develcon Electronics Ltd.
UUCP: ...watmath!dvlmarv!richards    515 Consumers Road, Suite 500,
                                     Willowdale, Ont, Canada M2J 4Z2
                                     (416) 495-8666 (B)
                                     (416) 665-6248 (H)

piet@cs.ruu.nl (Piet van Oostrum) (06/23/89)

In article <8906221536.AA26520@dvlmarv.UUCP>, gatech!dvlmarv!richards@EDDIE (Richard Sewards) writes:
 `
 `
 `I've found a code generation bug in gcc 1.34 with the 68000 code generator.
 `The following is the assembler output (and corresponding source lines) where
 `the problem occurs and after that I'm including the entire (preprocessed)
 `source file which generates the bug with comments at the lines where the
 `problem is.
 `
 `The problems is that for register pointer variables compared with 0 a
 `word comparison is done instead of a long comparison.
 `
 `			cmpw #0,a2

This is not a bug, it is a feature. The 68000 instruction actually used is
a cmpa (compare address register). If this instruction is used with a word
operand that operand is sign-extended, and then compared with the 32-bit
address register. So it does the same as the long version, but is 2 bytes
shorter. 
-- 
Piet van Oostrum, Dept of Computer Science, University of Utrecht
Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands
Telephone: +31-30-531806. piet@cs.ruu.nl (mcvax!hp4nl!ruuinf!piet)