aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2015-12-08 21:06:42 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2015-12-08 21:06:42 +0000
commit4d5438cd3cc48733f76f65aaad34475c06468886 (patch)
tree3d11ba1bdd590dbdd7d67612073526bcf864f0da
parent41c60c6c75356bfe5e4ce11184b4bf62a6a86132 (diff)
downloadgcc-4d5438cd3cc48733f76f65aaad34475c06468886.zip
gcc-4d5438cd3cc48733f76f65aaad34475c06468886.tar.gz
gcc-4d5438cd3cc48733f76f65aaad34475c06468886.tar.bz2
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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/nvptx/nvptx.c189
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/gcc.target/nvptx/trailing-init.c18
4 files changed, 125 insertions, 97 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e186901..1668e4e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+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>
PR middle-end/68291
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 5a32ade..d9ccb81 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -1484,73 +1484,70 @@ nvptx_hard_regno_mode_ok (int regno, machine_mode mode)
return mode == cfun->machine->ret_reg_mode;
}
-/* Machinery to output constant initializers. When beginning an initializer,
- we decide on a chunk size (which is visible in ptx in the type used), and
- then all initializer data is buffered until a chunk is filled and ready to
- be written out. */
-
-/* Used when assembling integers to ensure data is emitted in
- pieces whose size matches the declaration we printed. */
-static unsigned int decl_chunk_size;
-static machine_mode decl_chunk_mode;
-/* Used in the same situation, to keep track of the byte offset
- into the initializer. */
-static unsigned HOST_WIDE_INT decl_offset;
-/* The initializer part we are currently processing. */
-static HOST_WIDE_INT init_part;
-/* The total size of the object. */
-static unsigned HOST_WIDE_INT object_size;
-/* True if we found a skip extending to the end of the object. Used to
- assert that no data follows. */
-static bool object_finished;
-
-/* Write the necessary separator string to begin a new initializer value. */
+/* Machinery to output constant initializers. When beginning an
+ initializer, we decide on a fragment size (which is visible in ptx
+ in the type used), and then all initializer data is buffered until
+ a fragment is filled and ready to be written out. */
+
+static struct
+{
+ unsigned HOST_WIDE_INT mask; /* Mask for storing fragment. */
+ unsigned HOST_WIDE_INT val; /* Current fragment value. */
+ unsigned HOST_WIDE_INT remaining; /* Remaining bytes to be written
+ out. */
+ unsigned size; /* Fragment size to accumulate. */
+ unsigned offset; /* Offset within current fragment. */
+ bool started; /* Whether we've output any initializer. */
+} init_frag;
+
+/* The current fragment is full, write it out. SYM may provide a
+ symbolic reference we should output, in which case the fragment
+ value is the addend. */
static void
-begin_decl_field (void)
+output_init_frag (rtx sym)
{
- /* We never see decl_offset at zero by the time we get here. */
- if (decl_offset == decl_chunk_size)
- fprintf (asm_out_file, " = { ");
- else
- fprintf (asm_out_file, ", ");
-}
+ fprintf (asm_out_file, init_frag.started ? ", " : " = { ");
+ unsigned HOST_WIDE_INT val = init_frag.val;
-/* 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
-output_decl_chunk (void)
-{
- begin_decl_field ();
- output_address (VOIDmode, gen_int_mode (init_part, decl_chunk_mode));
- init_part = 0;
+ if (!sym || val)
+ fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, val);
}
-/* Add value VAL sized SIZE to the data we're emitting, and keep writing
- out chunks as they fill up. */
+/* Add value VAL of size SIZE to the data we're emitting, and keep
+ writing out chunks as they fill up. */
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;
- gcc_assert (!object_finished);
- while (size > 0)
+ val &= ((unsigned HOST_WIDE_INT)2 << (size * BITS_PER_UNIT - 1)) - 1;
+
+ for (unsigned part = 0; size; size -= part)
{
- int this_part = size;
- if (chunk_offset + this_part > decl_chunk_size)
- this_part = decl_chunk_size - chunk_offset;
- HOST_WIDE_INT val_part;
- HOST_WIDE_INT mask = 2;
- mask <<= this_part * BITS_PER_UNIT - 1;
- val_part = val & (mask - 1);
- init_part |= val_part << (BITS_PER_UNIT * chunk_offset);
- val >>= BITS_PER_UNIT * this_part;
- size -= this_part;
- decl_offset += this_part;
- if (decl_offset % decl_chunk_size == 0)
- output_decl_chunk ();
-
- chunk_offset = 0;
+ val >>= part * BITS_PER_UNIT;
+ part = init_frag.size - init_frag.offset;
+ if (part > size)
+ part = size;
+
+ unsigned HOST_WIDE_INT partial
+ = val << (init_frag.offset * BITS_PER_UNIT);
+ init_frag.val |= partial & init_frag.mask;
+ init_frag.offset += part;
+
+ if (init_frag.offset == init_frag.size)
+ output_init_frag (NULL);
}
}
@@ -1567,8 +1564,7 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
gcc_unreachable ();
case CONST_INT:
- val = INTVAL (x);
- nvptx_assemble_value (val, size);
+ nvptx_assemble_value (INTVAL (x), size);
break;
case CONST:
@@ -1580,19 +1576,13 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
/* FALLTHROUGH */
case SYMBOL_REF:
- gcc_assert (size = decl_chunk_size);
- if (decl_offset % decl_chunk_size != 0)
+ gcc_assert (size == init_frag.size);
+ if (init_frag.offset)
sorry ("cannot emit unaligned pointers in ptx assembly");
- decl_offset += size;
- begin_decl_field ();
nvptx_maybe_record_fnsym (x);
- fprintf (asm_out_file, "generic(");
- output_address (VOIDmode, x);
- fprintf (asm_out_file, ")");
-
- if (val)
- fprintf (asm_out_file, " + " HOST_WIDE_INT_PRINT_DEC, val);
+ init_frag.val = val;
+ output_init_frag (x);
break;
}
@@ -1606,21 +1596,28 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
void
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)
- nvptx_assemble_value (0, decl_chunk_size);
- object_finished = true;
- return;
+ unsigned part = init_frag.size - init_frag.offset;
+ if (part > size)
+ part = (unsigned) size;
+ 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);
- size -= decl_chunk_size;
+ while (size >= init_frag.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
@@ -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 &= -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;
- object_finished = !size;
+ init_frag.size = elt_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 ",
section, align / BITS_PER_UNIT,
@@ -1680,8 +1680,7 @@ nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section,
if (size)
/* We make everything an array, to simplify any initialization
emission. */
- fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]",
- (size + elt_size - 1) / elt_size);
+ fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]", init_frag.remaining);
}
/* 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,
static void
nvptx_assemble_decl_end (void)
{
- if (decl_offset != 0)
- {
- if (!object_finished && decl_offset % decl_chunk_size != 0)
- nvptx_assemble_value (0, decl_chunk_size);
-
- fprintf (asm_out_file, " }");
- }
- fprintf (asm_out_file, ";\n");
+ if (init_frag.offset)
+ /* This can happen with a packed struct with trailing array member. */
+ nvptx_assemble_value (0, init_frag.size - init_frag.offset);
+ fprintf (asm_out_file, init_frag.started ? " };\n" : ";\n");
}
/* Output an uninitialized common or file-scope variable. */
@@ -1714,7 +1709,7 @@ nvptx_output_aligned_decl (FILE *file, const char *name,
nvptx_assemble_decl_begin (file, name, section_for_decl (decl),
TREE_TYPE (decl), size, align);
- fprintf (file, ";\n");
+ nvptx_assemble_decl_end ();
}
/* Implement TARGET_ASM_DECLARE_CONSTANT_NAME. Begin the process of
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fe06f71..b596b03 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,7 @@
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/pr33855.c: Likewise.
* gcc.c-torture/execute/981019-1.c: Remove PTX -O2 skip.
diff --git a/gcc/testsuite/gcc.target/nvptx/trailing-init.c b/gcc/testsuite/gcc.target/nvptx/trailing-init.c
new file mode 100644
index 0000000..3fa916d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/trailing-init.c
@@ -0,0 +1,18 @@
+/* { 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 };" } } */