[gnu.gcc.bug] GCC-1.36 optimizer bug

pme@EDDIE.MIT.EDU (Paul English x3168) (10/04/89)

I sent in this bug a few weeks ago, but now have more info from Kimbo
Mundy (kimbo@ileaf.com). Thus I'll restate the bug. (And could you at
least acknowledge receiving this bug report?)

First, here is the program with the original description:

-------------------- cut here --------------------
/* This program illustrates a bug in the gcc optimizer.
 * Execute the following:
 *	gcc -g -O thisfile.c
 *	a.out
 *	face = 0	<incorrect>
 *	gcc -O thisfile.c
 *	a.out
 *	face = 0	<incorrect>
 *	gcc -g thisfile.c
 *	face = 8	<correct>
 * (I did not try to get the absolutely minimal piece of code
 * that would recreate the problem.)
 *
 * The problem seems to be that the line:
 *    new_ital = c & FN_ITALIC_FACE;
 * seems to be optimized away, along with the variable "new_ital".
 */

#define FID_FACE_SHIFT	    8
#define FID_BOLD_FACE	    0x00000100
#define FID_ITALIC_FACE	    0x00000200

#define FN_BOLD_FACE	(FID_BOLD_FACE >> FID_FACE_SHIFT)
#define FN_ITALIC_FACE	(FID_ITALIC_FACE >> FID_FACE_SHIFT)

#define FN_BOLD_FACE_SAME	0L
#define FN_BOLD_FACE_TOGGLE	1L
#define FN_ITALIC_FACE_SAME	0L
#define FN_ITALIC_FACE_TOGGLE	(1L<<3)

short bmodify;

LoadFont(face)
long face;
{
    printf("face = %d\n", face);
}

short
EcGetFontFamily( font)
short	font;
{
    return 0;
}

short
EcGetFontSize( font)
short	font;
{
    return 10;
}

short
EcGetFontFace( font)
short	font;
{
    return (font == 0 ? 0 : FN_ITALIC_FACE);
}

void
EcCmpnChangeDfont(new_font, delete_redundant)
int		new_font;
short		delete_redundant;
{
    register short*	cp;
    register short	c;
    register short*	end;
    register short	new_change = -1, cur_font = -1;
    short		change_to = -1;
    short		old_font, old_fmly, old_size, old_bold, old_ital;
    short		new_fmly, new_size, new_bold, new_ital;
    long		face;
    register short*	temp;

    if ( ( old_font = 0) == new_font )
	return;

    bmodify += 1;

    new_fmly = EcGetFontFamily(new_font);
    new_size = EcGetFontSize(new_font);
    c = EcGetFontFace(new_font);
    new_bold = c & FN_BOLD_FACE;
    new_ital = c & FN_ITALIC_FACE;

    old_fmly = EcGetFontFamily(old_font);
    old_size = EcGetFontSize(old_font);
    c = EcGetFontFace(old_font);
    old_bold = c & FN_BOLD_FACE;
    old_ital = c & FN_ITALIC_FACE;

    face = ((new_bold^old_bold) ? FN_BOLD_FACE_TOGGLE : FN_BOLD_FACE_SAME)|
	((new_ital^old_ital) ? FN_ITALIC_FACE_TOGGLE : FN_ITALIC_FACE_SAME);
    LoadFont(face);
}

main()
{
    EcCmpnChangeDfont(1, 0);
}
-------------------- cut here --------------------

In combine.c:try_distrib, there is this comment:

  /* ??? Need to implement a test that PREV2 and PREV1
     are completely independent.  Right now their
     recognition ability is sufficiently limited that
     it should not be necessary, but better safe than sorry.  */

I fear that this may be the source of the bug. In particular, it
appears that the code is trying to distribute the ANDs through the XOR
in the following lines from the above program:

    new_ital = c & FN_ITALIC_FACE;
	...
    old_ital = c & FN_ITALIC_FACE;
	...
	((new_ital^old_ital) ? ...

It decides it can do this and end up with (effectively):

	((c ^ c) & FN_ITALIC_FACE) ? ...

In essence, the lifetime information of c in the new_ital line is lost.