Commit 4d5438cd by Nathan Sidwell Committed by Nathan Sidwell

nvptx.c (decl_chunk_size, [...]): Replace with ...

	gcc/
	* config/nvptx/nvptx.c (decl_chunk_size, decl_chunk_mode,
	decl_offset, init_part, object_size, object_finished): Replace
	with ...
	(struct init_frag): ... this new struct variable.
	(begin_decl_field, output_decl_chunk): Replace with ...
	(output_init_frag): ... this new function.
	(nvptx_assemble_value): Reimplement.
	(nvptx_assemble_integer, nvptx_output_skip): Adjust.
	(nvptx_assemble_decl_begin, nvptx_assemble_decl_end): Adjust.
	(nvptx_output_aligned_decl): Call nvptx_assemble_decl_end.

	gcc/testsuite/
	* gcc.target/nvptx/trailing-init.c: New.

From-SVN: r231426
parent 41c60c6c
2015-12-08 Nathan Sidwell <nathan@acm.org>
* config/nvptx/nvptx.c (decl_chunk_size, decl_chunk_mode,
decl_offset, init_part, object_size, object_finished): Replace
with ...
(struct init_frag): ... this new struct variable.
(begin_decl_field, output_decl_chunk): Replace with ...
(output_init_frag): ... this new function.
(nvptx_assemble_value): Reimplement.
(nvptx_assemble_integer, nvptx_output_skip): Adjust.
(nvptx_assemble_decl_begin, nvptx_assemble_decl_end): Adjust.
(nvptx_output_aligned_decl): Call nvptx_assemble_decl_end.
2015-12-08 Eric Botcazou <ebotcazou@adacore.com> 2015-12-08 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/68291 PR middle-end/68291
...@@ -1484,73 +1484,70 @@ nvptx_hard_regno_mode_ok (int regno, machine_mode mode) ...@@ -1484,73 +1484,70 @@ nvptx_hard_regno_mode_ok (int regno, machine_mode mode)
return mode == cfun->machine->ret_reg_mode; return mode == cfun->machine->ret_reg_mode;
} }
/* Machinery to output constant initializers. When beginning an initializer, /* Machinery to output constant initializers. When beginning an
we decide on a chunk size (which is visible in ptx in the type used), and initializer, we decide on a fragment size (which is visible in ptx
then all initializer data is buffered until a chunk is filled and ready to in the type used), and then all initializer data is buffered until
be written out. */ a fragment is filled and ready to be written out. */
/* Used when assembling integers to ensure data is emitted in static struct
pieces whose size matches the declaration we printed. */ {
static unsigned int decl_chunk_size; unsigned HOST_WIDE_INT mask; /* Mask for storing fragment. */
static machine_mode decl_chunk_mode; unsigned HOST_WIDE_INT val; /* Current fragment value. */
/* Used in the same situation, to keep track of the byte offset unsigned HOST_WIDE_INT remaining; /* Remaining bytes to be written
into the initializer. */ out. */
static unsigned HOST_WIDE_INT decl_offset; unsigned size; /* Fragment size to accumulate. */
/* The initializer part we are currently processing. */ unsigned offset; /* Offset within current fragment. */
static HOST_WIDE_INT init_part; bool started; /* Whether we've output any initializer. */
/* The total size of the object. */ } init_frag;
static unsigned HOST_WIDE_INT object_size;
/* True if we found a skip extending to the end of the object. Used to /* The current fragment is full, write it out. SYM may provide a
assert that no data follows. */ symbolic reference we should output, in which case the fragment
static bool object_finished; value is the addend. */
/* Write the necessary separator string to begin a new initializer value. */
static void static void
begin_decl_field (void) output_init_frag (rtx sym)
{ {
/* We never see decl_offset at zero by the time we get here. */ fprintf (asm_out_file, init_frag.started ? ", " : " = { ");
if (decl_offset == decl_chunk_size) unsigned HOST_WIDE_INT val = init_frag.val;
fprintf (asm_out_file, " = { ");
else
fprintf (asm_out_file, ", ");
}
/* Output the currently stored chunk as an initializer value. */ init_frag.started = true;
init_frag.val = 0;
init_frag.offset = 0;
init_frag.remaining--;
if (sym)
{
fprintf (asm_out_file, "generic(");
output_address (VOIDmode, sym);
fprintf (asm_out_file, val ? ") + " : ")");
}
static void if (!sym || val)
output_decl_chunk (void) fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, val);
{
begin_decl_field ();
output_address (VOIDmode, gen_int_mode (init_part, decl_chunk_mode));
init_part = 0;
} }
/* Add value VAL sized SIZE to the data we're emitting, and keep writing /* Add value VAL of size SIZE to the data we're emitting, and keep
out chunks as they fill up. */ writing out chunks as they fill up. */
static void static void
nvptx_assemble_value (HOST_WIDE_INT val, unsigned int size) nvptx_assemble_value (unsigned HOST_WIDE_INT val, unsigned size)
{ {
unsigned HOST_WIDE_INT chunk_offset = decl_offset % decl_chunk_size; val &= ((unsigned HOST_WIDE_INT)2 << (size * BITS_PER_UNIT - 1)) - 1;
gcc_assert (!object_finished);
while (size > 0) for (unsigned part = 0; size; size -= part)
{ {
int this_part = size; val >>= part * BITS_PER_UNIT;
if (chunk_offset + this_part > decl_chunk_size) part = init_frag.size - init_frag.offset;
this_part = decl_chunk_size - chunk_offset; if (part > size)
HOST_WIDE_INT val_part; part = size;
HOST_WIDE_INT mask = 2;
mask <<= this_part * BITS_PER_UNIT - 1; unsigned HOST_WIDE_INT partial
val_part = val & (mask - 1); = val << (init_frag.offset * BITS_PER_UNIT);
init_part |= val_part << (BITS_PER_UNIT * chunk_offset); init_frag.val |= partial & init_frag.mask;
val >>= BITS_PER_UNIT * this_part; init_frag.offset += part;
size -= this_part;
decl_offset += this_part; if (init_frag.offset == init_frag.size)
if (decl_offset % decl_chunk_size == 0) output_init_frag (NULL);
output_decl_chunk ();
chunk_offset = 0;
} }
} }
...@@ -1567,8 +1564,7 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p)) ...@@ -1567,8 +1564,7 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
gcc_unreachable (); gcc_unreachable ();
case CONST_INT: case CONST_INT:
val = INTVAL (x); nvptx_assemble_value (INTVAL (x), size);
nvptx_assemble_value (val, size);
break; break;
case CONST: case CONST:
...@@ -1580,19 +1576,13 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p)) ...@@ -1580,19 +1576,13 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
/* FALLTHROUGH */ /* FALLTHROUGH */
case SYMBOL_REF: case SYMBOL_REF:
gcc_assert (size = decl_chunk_size); gcc_assert (size == init_frag.size);
if (decl_offset % decl_chunk_size != 0) if (init_frag.offset)
sorry ("cannot emit unaligned pointers in ptx assembly"); sorry ("cannot emit unaligned pointers in ptx assembly");
decl_offset += size;
begin_decl_field ();
nvptx_maybe_record_fnsym (x); nvptx_maybe_record_fnsym (x);
fprintf (asm_out_file, "generic("); init_frag.val = val;
output_address (VOIDmode, x); output_init_frag (x);
fprintf (asm_out_file, ")");
if (val)
fprintf (asm_out_file, " + " HOST_WIDE_INT_PRINT_DEC, val);
break; break;
} }
...@@ -1606,21 +1596,28 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p)) ...@@ -1606,21 +1596,28 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
void void
nvptx_output_skip (FILE *, unsigned HOST_WIDE_INT size) nvptx_output_skip (FILE *, unsigned HOST_WIDE_INT size)
{ {
if (decl_offset + size >= object_size) /* Finish the current fragment, if it's started. */
if (init_frag.offset)
{ {
if (decl_offset % decl_chunk_size != 0) unsigned part = init_frag.size - init_frag.offset;
nvptx_assemble_value (0, decl_chunk_size); if (part > size)
object_finished = true; part = (unsigned) size;
return; size -= part;
nvptx_assemble_value (0, part);
} }
while (size > decl_chunk_size) /* If this skip doesn't terminate the initializer, write as many
remaining pieces as possible directly. */
if (size < init_frag.remaining * init_frag.size)
{ {
nvptx_assemble_value (0, decl_chunk_size); while (size >= init_frag.size)
size -= decl_chunk_size; {
size -= init_frag.size;
output_init_frag (NULL_RTX);
}
if (size)
nvptx_assemble_value (0, size);
} }
while (size-- > 0)
nvptx_assemble_value (0, 1);
} }
/* Output a string STR with length SIZE. As in nvptx_output_skip we /* Output a string STR with length SIZE. As in nvptx_output_skip we
...@@ -1662,15 +1659,18 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section, ...@@ -1662,15 +1659,18 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section,
elt_size |= GET_MODE_SIZE (elt_mode); elt_size |= GET_MODE_SIZE (elt_mode);
elt_size &= -elt_size; /* Extract LSB set. */ elt_size &= -elt_size; /* Extract LSB set. */
elt_mode = mode_for_size (elt_size * BITS_PER_UNIT, MODE_INT, 0);
decl_chunk_size = elt_size;
decl_chunk_mode = elt_mode;
decl_offset = 0;
init_part = 0;
object_size = size; init_frag.size = elt_size;
object_finished = !size; /* Avoid undefined shift behaviour by using '2'. */
init_frag.mask = ((unsigned HOST_WIDE_INT)2
<< (elt_size * BITS_PER_UNIT - 1)) - 1;
init_frag.val = 0;
init_frag.offset = 0;
init_frag.started = false;
/* Size might not be a multiple of elt size, if there's an
initialized trailing struct array with smaller type than
elt_size. */
init_frag.remaining = (size + elt_size - 1) / elt_size;
fprintf (file, "%s .align %d .u%d ", fprintf (file, "%s .align %d .u%d ",
section, align / BITS_PER_UNIT, section, align / BITS_PER_UNIT,
...@@ -1680,8 +1680,7 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section, ...@@ -1680,8 +1680,7 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section,
if (size) if (size)
/* We make everything an array, to simplify any initialization /* We make everything an array, to simplify any initialization
emission. */ emission. */
fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]", fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]", init_frag.remaining);
(size + elt_size - 1) / elt_size);
} }
/* Called when the initializer for a decl has been completely output through /* Called when the initializer for a decl has been completely output through
...@@ -1690,14 +1689,10 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section, ...@@ -1690,14 +1689,10 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section,
static void static void
nvptx_assemble_decl_end (void) nvptx_assemble_decl_end (void)
{ {
if (decl_offset != 0) if (init_frag.offset)
{ /* This can happen with a packed struct with trailing array member. */
if (!object_finished && decl_offset % decl_chunk_size != 0) nvptx_assemble_value (0, init_frag.size - init_frag.offset);
nvptx_assemble_value (0, decl_chunk_size); fprintf (asm_out_file, init_frag.started ? " };\n" : ";\n");
fprintf (asm_out_file, " }");
}
fprintf (asm_out_file, ";\n");
} }
/* Output an uninitialized common or file-scope variable. */ /* Output an uninitialized common or file-scope variable. */
...@@ -1714,7 +1709,7 @@ nvptx_output_aligned_decl (FILE *file, const char *name, ...@@ -1714,7 +1709,7 @@ nvptx_output_aligned_decl (FILE *file, const char *name,
nvptx_assemble_decl_begin (file, name, section_for_decl (decl), nvptx_assemble_decl_begin (file, name, section_for_decl (decl),
TREE_TYPE (decl), size, align); TREE_TYPE (decl), size, align);
fprintf (file, ";\n"); nvptx_assemble_decl_end ();
} }
/* Implement TARGET_ASM_DECLARE_CONSTANT_NAME. Begin the process of /* Implement TARGET_ASM_DECLARE_CONSTANT_NAME. Begin the process of
......
2015-12-08 Nathan Sidwell <nathan@acm.org> 2015-12-08 Nathan Sidwell <nathan@acm.org>
* gcc.target/nvptx/trailing-init.c: New.
* gcc.c-torture/compile/920723-1.c: Remove PTX skip. * gcc.c-torture/compile/920723-1.c: Remove PTX skip.
* gcc.c-torture/compile/pr33855.c: Likewise. * gcc.c-torture/compile/pr33855.c: Likewise.
* gcc.c-torture/execute/981019-1.c: Remove PTX -O2 skip. * gcc.c-torture/execute/981019-1.c: Remove PTX -O2 skip.
......
/* { dg-additional-options "-Wno-pedantic" } */
struct trailing
{
unsigned m;
short ary[];
} trailing =
{.ary = {1}};
struct packed
{
unsigned m;
short ary[];
} __attribute__ ((packed)) packed =
{.ary = {2}};
/* { dg-final { scan-assembler ".align 1 .u32 packed\\\[2\\\] = { 0, 2 };" } } */
/* { dg-final { scan-assembler ".align 4 .u32 trailing\\\[2\\\] = { 0, 1 };" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment