This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
GCC endless loop for store_bit_field with alignment 0
- To: gcc-bugs at gcc dot gnu dot org
- Subject: GCC endless loop for store_bit_field with alignment 0
- From: David Edelsohn <dje at watson dot ibm dot com>
- Date: Thu, 10 Aug 2000 17:16:23 -0400
- cc: Geoff Keating <geoffk at cygnus dot com>, Richard Henderson <rth at cygnus dot com>
gcc.c-torture/compile/20000405-3.c causes GCC to enter an endless
loop when producing code for 64-bit PowerPC. Analyzing the problem has
uncovered a number of weird conditions in GCC, so I am not sure which is
the real problem that should be solved -- maybe both of them.
The testcase is the following simple code:
struct foo {
void *entry[40];
} __attribute__ ((aligned(32)));
int foo (struct foo *ptr, int idx, void *pointer)
{
ptr->entry[idx] = pointer;
return 0;
}
The endless loop occurs in store_split_bit_field() which
calculates the size of the subfield to move as zero (0) and never makes
any progress in its "while (bitsdone < bitsize)" loop.
The subfield size is calculated as zero because the alignment of
the whole field is zero, causing the "unit" to be zero:
/* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that
much at a time. */
if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
unit = BITS_PER_WORD;
else
unit = MIN (align, BITS_PER_WORD);
The alignment is zero because expr.c:get_inner_reference()
calculates a zero alignment when called from expr.c:expand_assignment() in
the COMPONENT_REF case:
if (! host_integerp (offset, 0))
alignment = MIN (alignment, DECL_OFFSET_ALIGN (field));
host_integerp returns false because the offset if a NON_LVALUE_EXPR and
DECL_OFFSET_ALIGN (field) returns 0, despite the fact that I don't see how
the alignment above could be less than MIN (32, alignof(void *)).
The testcase works in 32-bit mode because SLOW_UNALIGNED_ACCESS of
SImode with zero alignment is false but SLOW_UNALIGNED_ACCESS of DImode
with zero alignment is true. In 32-bit mode expr.c:store_field() calls
store_expr(), but in 64-bit mode store_bit_field() is called because of
the zero alignment making SLOW_UNALIGNED_ACCESS true for this BLKmode op.
The upshot is that I see two weird conditions:
1) Why does DECL_OFFSET_ALIGN return 0 for the declaration in the
testcase making the alignment zero?
2) Something must be wrong with store_split_bit_field()
calculating a zero unit size. Maybe it should be the
following:
if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
unit = BITS_PER_WORD;
else
unit = MAX (MIN (align, BITS_PER_WORD), BITS_PER_WORD);
Doesn't this bug occur for Alpha port as well which defines
SLOW_UNALIGNED_ACCESS uniformly as 1?
Thanks, David
===============================================================================
David Edelsohn T.J. Watson Research Center
dje@watson.ibm.com P.O. Box 218
+1 914 945 4364 (TL 862) Yorktown Heights, NY 10598