[gnu.gcc.bug] Problem with -fstrength-reduce

dennis@GW.CCIE.UTORONTO.CA (Dennis Ferguson) (06/08/89)

I am using gcc 1.35 on a Sun 3/180 running SunOS 3.5.  The compiler
was configured using `config.gcc sun3'.  I am using the Sun assembler
and loader.

The following program, when compiled with `gcc -O ...', produces correct
results, as it does when compiled with the Sun compiler.  When compiled
with `gcc -O -fstrength-reduce ...' it does not.  I tried to find a smaller
fragment which would exhibit the problem but found the trouble kept
disappearing on me.

Dennis Ferguson
------
#include <stdio.h>
typedef	unsigned char	u_char;
typedef	unsigned short	u_short;
typedef	unsigned int	u_int;
typedef	unsigned long	u_long;
u_char ekeys[128];
u_char dkeys[128];
u_long keys[10][2] = {
	0x00000000, 0x00000000,
	0xffffffff, 0xffffffff,
	0x30000000, 0x00000000,
	0x11111111, 0x11111111,
	0x01234567, 0x89abcdef,
	0xfedcba98, 0x76543210,
	0x7ca11045, 0x4a1a6e57,
	0x0131d961, 0x9dc1376e,
	0x07a1133e, 0x4a0b2686,
	0x3849674c, 0x2602319e
};
main()
{
	int i, j;
	for (i = 0; i < 10; i++) {
		auth_subkeys(&keys[i][0], ekeys, dkeys);
		(void) printf("0x%08x 0x%08x\n", keys[i][0], keys[i][1]);
		for (j = 0; j < 128; j++) {
			printf(" 0x%03x", ekeys[j]);
			if (j % 8 == 7)
				printf("\n");
		}
	}
}
static u_char PC1_C[28] = {
	56, 48, 40, 32, 24, 16,  8,
	 0, 57, 49, 41, 33, 25, 17,
	 9,  1, 58, 50, 42, 34, 26,
	18, 10,  2, 59, 51, 43, 35
};
static u_char PC1_D[28] = {
	62, 54, 46, 38, 30, 22, 14,
	 6, 61, 53, 45, 37, 29, 21,
	13,  5, 60, 52, 44, 36, 28,
	20, 12,  4, 27, 19, 11,  3
};
static u_char two_bit_shift[16] = {
	0, 0, 1, 1, 1, 1, 1, 1,
	0, 1, 1, 1, 1, 1, 1, 0
};
static u_char PC2_C[24] = {
	13, 16, 10, 23,  0,  4,
	 2, 27, 14,  5, 20,  9,
	22, 18, 11,  3, 25,  7,
	15,  6, 26, 19, 12,  1
};
static u_char PC2_D[24] = {
	12, 23,  2,  8, 18, 26,
	 1, 11, 22, 16,  4, 19,
	15, 20, 10, 27,  5, 24,
	17, 13, 21,  7,  0,  3
};
auth_subkeys(key, encryptkeys, decryptkeys)
	u_long *key;
	u_char *encryptkeys;
	u_char *decryptkeys;
{
	register u_char *ek, *dk;
	register int i;
	register u_char tempc;
	register u_long templ;
	register int iteration;
	u_char bits[64];	 
	u_char c[28], d[28];	 
	templ = *key;
	for (i = 0; i < 32; i++) {
		bits[i] = ((templ & 0x80000000) != 0);
		templ <<= 1;
	}
	templ = *(key+1);
	for ( ; i < 64; i++) {
		bits[i] = ((templ & 0x80000000) != 0);
		templ <<= 1;
	}
	for (i = 0; i < 28; i++) {
		c[i] = bits[PC1_C[i]];
		d[i] = bits[PC1_D[i]];
	}
	ek = encryptkeys;
	dk = decryptkeys + (8 * 15);
	for (iteration = 0; iteration < 16; iteration++) {
		if (two_bit_shift[iteration]) {
			tempc = c[0];
			templ = c[1];
			for (i = 0; i < 26; i++)
				c[i] = c[i+2];
			c[26] = tempc;
			c[27] = (u_char)templ;
			tempc = d[0];
			templ = d[1];
			for (i = 0; i < 26; i++)
				d[i] = d[i+2];
			d[26] = tempc;
			d[27] = (u_char)templ;
		} else {
			tempc = c[0];
			for (i = 0; i < 27; i++)
				c[i] = c[i+1];
			c[27] = tempc;
			tempc = d[0];
			for (i = 0; i < 27; i++)
				d[i] = d[i+1];
			d[27] = tempc;
		}
		for (i = 0; i < 24; i += 6) {
			tempc = (c[PC2_C[i]] << 5)
			      | (c[PC2_C[i+1]] << 4)
			      | (c[PC2_C[i+2]] << 3)
			      | (c[PC2_C[i+3]] << 2)
			      | (c[PC2_C[i+4]] << 1)
			      |  c[PC2_C[i+5]];
			*ek++ = *dk++ = tempc;
		}
		for (i = 0; i < 24; i += 6) {
			tempc = (d[PC2_D[i]] << 5)
			      | (d[PC2_D[i+1]] << 4)
			      | (d[PC2_D[i+2]] << 3)
			      | (d[PC2_D[i+3]] << 2)
			      | (d[PC2_D[i+4]] << 1)
			      |  d[PC2_D[i+5]];
			*ek++ = *dk++ = tempc;
		}
		dk -= 16;
	}
}