aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>1997-01-24 21:43:41 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>1997-01-24 21:43:41 +0000
commit91674c376c5dea02e83f28c44a76f4f555f53e37 (patch)
treed4636a6890102984b597b02aeb965528e9cad529 /gcc/varasm.c
parent38734e55b348c29115121efadb90275d3f150e81 (diff)
downloadgcc-91674c376c5dea02e83f28c44a76f4f555f53e37.zip
gcc-91674c376c5dea02e83f28c44a76f4f555f53e37.tar.gz
gcc-91674c376c5dea02e83f28c44a76f4f555f53e37.tar.bz2
Garbage collect constant pool entries and don't output unnecessary ones
From-SVN: r13550
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 7595f48..1bf3e51 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -143,6 +143,8 @@ static int compare_constant_rtx PROTO((enum machine_mode, rtx,
static struct constant_descriptor *record_constant_rtx PROTO((enum machine_mode,
rtx));
static struct pool_constant *find_pool_constant PROTO((rtx));
+static void mark_constant_pool PROTO((void));
+static void mark_constants PROTO((rtx));
static int output_addressed_constants PROTO((tree));
static void output_after_function_constants PROTO((void));
static void bc_assemble_integer PROTO((tree, int));
@@ -3116,6 +3118,7 @@ struct pool_constant
int labelno;
int align;
int offset;
+ int mark;
};
/* Pointers to first and last constant in pool. */
@@ -3483,6 +3486,7 @@ force_const_mem (mode, x)
pool->labelno = const_labelno;
pool->align = align;
pool->offset = pool_offset;
+ pool->mark = 0;
pool->next = 0;
if (last_pool == 0)
@@ -3596,6 +3600,12 @@ output_constant_pool (fnname, fndecl)
rtx x;
union real_extract u;
+ /* It is possible for gcc to call force_const_mem and then to later
+ discard the instructions which refer to the constant. In such a
+ case we do not need to output the constant. */
+ if (flag_expensive_optimizations)
+ mark_constant_pool ();
+
#ifdef ASM_OUTPUT_POOL_PROLOGUE
ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset);
#endif
@@ -3604,6 +3614,9 @@ output_constant_pool (fnname, fndecl)
{
x = pool->constant;
+ if (flag_expensive_optimizations && ! pool->mark)
+ continue;
+
/* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF)
whose CODE_LABEL has been deleted. This can occur if a jump table
is eliminated by optimization. If so, write a constant of zero
@@ -3666,6 +3679,89 @@ output_constant_pool (fnname, fndecl)
/* Done with this pool. */
first_pool = last_pool = 0;
}
+
+/* Look through the instructions for this function, and mark all the
+ entries in the constant pool which are actually being used. */
+
+static void
+mark_constant_pool ()
+{
+ register rtx insn;
+
+ if (first_pool == 0)
+ return;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ mark_constants (PATTERN (insn));
+
+ for (insn = current_function_epilogue_delay_list;
+ insn;
+ insn = XEXP (insn, 1))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ mark_constants (PATTERN (insn));
+}
+
+static void
+mark_constants (x)
+ register rtx x;
+{
+ register int i;
+ register char *format_ptr;
+
+ if (x == 0)
+ return;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ if (CONSTANT_POOL_ADDRESS_P (x))
+ find_pool_constant (x)->mark = 1;
+ return;
+ }
+
+ /* Insns may appear inside a SEQUENCE. Only check the patterns of
+ insns, not any notes that may be attached. We don't want to mark
+ a constant just because it happens to appear in a REG_EQUIV note. */
+ if (GET_RTX_CLASS (GET_CODE (x)) == 'i')
+ {
+ mark_constants (PATTERN (x));
+ return;
+ }
+
+ format_ptr = GET_RTX_FORMAT (GET_CODE (x));
+
+ for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
+ {
+ switch (*format_ptr++)
+ {
+ case 'e':
+ mark_constants (XEXP (x, i));
+ break;
+
+ case 'E':
+ if (XVEC (x, i) != 0)
+ {
+ register int j;
+
+ for (j = 0; j < XVECLEN (x, i); j++)
+ mark_constants (XVECEXP (x, i, j));
+ }
+ break;
+
+ case 'S':
+ case 's':
+ case '0':
+ case 'i':
+ case 'w':
+ case 'n':
+ case 'u':
+ break;
+
+ default:
+ abort ();
+ }
+ }
+}
/* Find all the constants whose addresses are referenced inside of EXP,
and make sure assembler code with a label has been output for each one.