This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

GCC endless loop for store_bit_field with alignment 0


	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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]