[gnu.gcc.bug] Bug in gcc 1.32

jay@bagel.key.com (Jay Pattin) (03/10/89)

I have encountered a bug in the global register allocator phase of gcc
version 1.32 for the Sun 3, running SunOS 3.5, when gcc is invoked
with the -O and -traditional options. Unfortunately, the smallest test
case for it about 2400 lines of code, plus declarations. I will send
the test case under separate cover in hopes that a shorter message
will be received faster, and that someone may already have encountered
this.

The example contains the following declaration for 'word'.

typedef		struct
{
	bits		h;	/* high half */
	bits		l;	/* low half */
}		word;

In a piece of code which uses a variable of type word and accesses the
'h' half several times, followed by the 'l' half several times, the
references to the 'l' half fail: they also access the 'h' half.

The combine phase converts the last reference to the 'h' half into a
post_increment (tuple 3990 in the lreg dump) address access with the
intention that accesses to the 'l' variable can then use that
information. However, the greg dump shows that the post_increment has
disappeared. We can't figure out reload (yet).

The variable in question is $CPU_7DIC107P$ICB5. Here's the excerpted
code:

	$CPU_7DIC107P$ICB5.h &= ~0xF;
	$CPU_7DIC107P$ICB5.h |= Pin_CB[10][10].p_value.l & 0xF;
	$CPU_7DIC107P$ICB5.h &= ~0xF0;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.l & 0x1E0) >> 1;
	$CPU_7DIC107P$ICB5.h &= ~0xF00;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.l & 0x3C00) >> 2;
	$CPU_7DIC107P$ICB5.h &= ~0xF000;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.l & 0x78000) >> 3;
	$CPU_7DIC107P$ICB5.h &= ~0xF0000;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.l & 0xF00000) >> 4;
	$CPU_7DIC107P$ICB5.h &= ~0xF00000;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.l & 0x1E000000) >> 5;
	$CPU_7DIC107P$ICB5.h &= ~0x3000000;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.l & 0xC0000000) >> 6;
	$CPU_7DIC107P$ICB5.h &= ~0xC000000;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.h & 0x3) << 26;
	$CPU_7DIC107P$ICB5.h &= ~0xF0000000;
	$CPU_7DIC107P$ICB5.h |= (Pin_CB[10][10].p_value.h & 0x78) << 25;

	CB11(cur_time,fpout,fperr);

	$CPU_7DIC107P$ICB5.l &= 0x1234567;

In lreg dump:

POINTER TO $CPU_7DIC107P$ICB5.h

(insn 3845 3844 3846 (set (reg:SI 3099)
       (symbol_ref:SI ("$CPU_7DIC107P$ICB5"))) 32 (nil)
   (expr_list (symbol_ref:SI ("$CPU_7DIC107P$ICB5"))
       (nil)))

LAST REFERENCE TO $CPU_7DIC107P$ICB5.h

(insn 3990 3989 3991 (set (mem/s:SI (post_inc:SI (reg:SI 3099)))
       (ior:SI (reg:SI 3211)
           (mem/s:SI (reg:SI 3099)))) 138 (insn_list 3989 (insn_list 3988 (nil)))
   (expr_list:QI (reg:SI 3211)
       (expr_list:HI (reg:SI 3099)
           (nil))))

POINTER TO $CPU_7DIC107P$ICB5.l (copied straight from .h)

(insn 4256 4255 4257 (set (reg:SI 3428)
       (reg:SI 3099)) 32 (nil)
   (expr_list:QI (reg:SI 3099)
       (expr_list:SI (const:SI (plus:SI (symbol_ref:SI ("$CPU_7DIC107P$ICB5"))
                   (const_int 4)))
           (expr_list:SI (const:SI (plus:SI (symbol_ref:SI ("$CPU_7DIC107P$ICB5"))
                       (const_int 4)))
               (nil)))))

In greg dump:

LAST REF to $CPU_7DIC107P$ICB5.h, note post_inc has disappeared

(insn:QI 3990 3989 3991 (set (mem/s:SI (reg:SI 12))
       (ior:SI (mem/s:SI (reg:SI 12))
           (reg:SI 0))) 138 (insn_list 3989 (insn_list 3988 (nil)))
   (expr_list:QI (reg:SI 0)
       (expr_list:HI (reg:SI 12)
           (nil))))

and we are still just copying the pointer.

(insn:QI 4256 4255 4257 (set (reg:SI 9)
       (reg:SI 12)) 32 (nil)
   (expr_list:QI (mem:SI (plus:SI (reg:SI 14)
               (const_int -40)))
       (expr_list:SI (const:SI (plus:SI (symbol_ref:SI ("$CPU_7DIC107P$ICB5"))
                   (const_int 4)))
           (expr_list:SI (const:SI (plus:SI (symbol_ref:SI ("$CPU_7DIC107P$ICB5"))
                       (const_int 4)))
               (nil)))))

-- Jay Pattin

jay@key.com
key!jay@mordor.s1.gov